我是哈希函数的初学者。我尝试使用哈希来实现子串相等问题。
问题描述
输入格式。第一行包含一个由小拉丁字母组成的字符串?。第二行包含 查询的数量?。接下来的每一行 ? 都用三个整数 ?、? 和 ? 指定一个查询。
约束。 1 ≤ |?| ≤ 500 000. 1 ≤ ? ≤ 100 000. 0 ≤ ?, ? ≤ |?| − ?(因此索引 ? 和 ? 是基于 0 的)。
输出格式。对于每个查询,如果????+1,则输出“是”。 . .??+?−1 = ????+1。 . .??+?−1 是相等的,并且“否” 否则。
示例 1。 输入: 托洛洛
4
0 0 7
2 4 3
3 5 1
1 3 2
输出:
是的
是的
是的
没有
0 0 7 → trololo = trololo
2 4 3 → trololo = trololo
3 5 1 → trololo = trololo
1 3 2 → trololo ̸= trololo
我使用了以下算法
allocate ℎ1[0..?]
ℎ1[0] ← 0
for ? from 1 to ?:
ℎ1[?] ← (? · ℎ1[? − 1] + ??) mod ?1
(a) 使用预先计算的哈希值,计算子串的哈希值????+1 · · · ??+?−1 和 ????+1 · · · ??+?−1 模?1 和?2。
(b) 输出“是”,如果 ?(?? ??+1 · · · ??+?−1) mod ?1 = ?(?? ??+1 · · ??+ mod?−1) ?(?? ??+1 · · · ??+?−1) mod ?2 = ?(?? ??+1 · · ??+ mod?-p>2
(c) 否则,输出“No”。
最后为了计算哈希值我使用了这个关系
?(?? ??+1 · · · ??+?−1) = ℎ[? + ?] − ?^l*ℎ[?] .
我尝试用 C++ 编写代码,它适用于大多数情况,但仅在一种情况下失败
Failed case:
input string : abacabadabacaba
a ,b ,l: 0 8 7
My Output : No
But the output should be 'Yes' as we 'abacaba' for both a to l and b to l
我不确定问题是什么,但是当我在 python 中编码时,它在这种情况下运行良好,并且对于上述情况结果是。谁能帮我理解原因。
我的代码:
C++
#include <iostream>
#include <vector>
#include <cmath>
#include <bits/stdc++.h>
using namespace std;
class Solver {
string s;
public:
Solver(string s) : s(s) {
// initialization, precalculation
}
bool ask(int a, int b, int l) {
return s.substr(a, l) == s.substr(b, l);
}
vector<long long int> HashTable(string s,long long int prime,long long int x){
vector<long long int> H(s.length()+1,0);
H[0] = 0;
for(int i=1;i<s.length()+1;i++)
{
H[i] = ((H[i-1] * x + (int)(s[i-1])) % prime);
}
return H;
}
vector<long long int> powernew(int length,long long int prime,long long int x)
{
vector<long long int> pow1(length+1,0);
pow1[0] = 1;
for(int i=1;i<length+1;i++)
{
pow1[i] = (long long int)(fmod(pow(x,i),prime));
}
return pow1;
}
long long int HashValue(vector<long long int> hash_table,long long int prime,long long int x,int start,int length,vector<long long int> y)
{
long long int hash_value = ((prime + (hash_table[start + length] - y[length] * hash_table[start]) % prime) % prime);
return hash_value;
}
bool ask_fast(int a,int b,int l,string s,long long int m1,long long int m2,long long int x,vector<long long int> y1,
vector<long long int> y2,vector<long long int> hash_table1,vector<long long int> hash_table2)
{
if(l==0)
return (s[a] == s[b]);
long long int a_hash1 = HashValue(hash_table1,m1,x,a,l,y1);
long long int a_hash2 = HashValue(hash_table2,m2,x,a,l,y2);
cout<<a_hash1<<" "<<a_hash2<<endl;
cout<<s[a]<<s[a+l-1]<<endl;
long long int b_hash1 = HashValue(hash_table1,m1,x,b,l,y1);
long long int b_hash2 = HashValue(hash_table2,m2,x,b,l,y2);
cout<<b_hash1<<" "<<b_hash2<<endl;
cout<<s[b]<<s[b+l-1]<<endl;
if((a_hash1 == b_hash1) && (a_hash2 == b_hash2))
return true;
else
return false;
}
};
int main() {
ios_base::sync_with_stdio(0), cin.tie(0);
string s;
int q;
cin >> s >> q;
Solver solver(s);
//Added
long long int m1 = 1000000000 + 7;
long long int m2 = 1000000000 + 9;
long long int x = 263;
vector<long long int> y1 = solver.powernew(s.length(),m1,x);
vector<long long int> y2 = solver.powernew(s.length(),m2,x);
vector<int> hash_table1 = solver.HashTable(s,m1,x);
vector<int> hash_table2 = solver.HashTable(s,m2,x);
//
for (int i = 0; i < q; i++) {
int a, b, l;
cin >> a >> b >> l;
cout << (solver.ask_fast(a, b, l, s,m1,m2,x,y1,y2,hash_table1,hash_table2) ? "Yes\n" : "No\n");
}
}
Python
# python3
import sys
class Solver:
def __init__(self, s):
self.s = s
def ask(self, a, b, l):
return s[a:a+l] == s[b:b+l]
def HashTable(self,s,prime,x):
H = list([] for _ in range(len(s)+1))
H[0] = 0
for i in range(1,len(s)+1):
H[i] = (H[i-1] * x + ord(s[i-1])) % prime
return H
def powernew(self,length,prime,x):
pow1 = list([] for _ in range(length+1))
pow1[0] = 1
for i in range(1,length+1):
pow1[i] = pow(x,i,prime)
return pow1
def HashValue(self,hash_table,prime,x,start,length,y):
hash_value = ((prime + (hash_table[start + length] - y[length] * hash_table[start]) % prime) % prime)
return hash_value
def ask_fast(self,a,b,l,s,m1,m2,x,y1,y2,hash_table1,hash_table2):
a_hash1 = self.HashValue(hash_table1,m1,x,a,l,y1)
a_hash2 = self.HashValue(hash_table2,m2,x,a,l,y2)
b_hash1 = self.HashValue(hash_table1,m1,x,b,l,y1)
b_hash2 = self.HashValue(hash_table2,m2,x,b,l,y2)
if (a_hash1 == b_hash1) and (a_hash2 == b_hash2):
return True
else:
return False
s = sys.stdin.readline()
q = int(sys.stdin.readline())
#s = input()
#q = int(input())
solver = Solver(s)
#added
m1 = 1000000007
m2 = 1000000009
x = 263
y1 = solver.powernew(len(s),m1,x)
y2 = solver.powernew(len(s),m2,x)
hash_table1 = solver.HashTable(s,m1,x)
hash_table2 = solver.HashTable(s,m2,x)
#ends
for i in range(q):
a, b, l = map(int, sys.stdin.readline().split())
#a, b, l = map(int, input().split())
#print("Yes" if solver.ask(a, b, l) else "No")
print("Yes" if solver.ask_fast(a, b, l, s, m1, m2, x, y1, y2, hash_table1, hash_table2) else "No")