使用哈希函数的子串相等问题

时间:2021-04-07 05:02:57

标签: python c++ hash

我是哈希函数的初学者。我尝试使用哈希来实现子串相等问题。

问题描述

输入格式。第一行包含一个由小拉丁字母组成的字符串?。第二行包含 查询的数量?。接下来的每一行 ? 都用三个整数 ?、? 和 ? 指定一个查询。

约束。 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

我使用了以下算法

  1. 修正 ?1 = 10^9 + 7 和 ?2 = 10^9 + 9。
  2. 从 1 到 10^9 中随机选择一个 ?。 (我选择 x = 263,因为大数字会导致上电时溢出)
  3. 计算数组 ℎ1[0..?] 和 ℎ2[0..?]: ℎ1[0] = ℎ2[0] = 0 并且,对于 1 ≤ ? ≤ ?,ℎ1[?] = ?(?) · · ??−1) mod ?1 和 ℎ2[?] = ?(?0 · · · ??−1) mod ?2。我们在下面的 ℎ1 中对此进行了说明。
allocate ℎ1[0..?]

ℎ1[0] ← 0

for ? from 1 to ?:

    ℎ1[?] ← (? · ℎ1[? − 1] + ??) mod ?1

  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")


0 个答案:

没有答案
相关问题