前缀字符串和前缀哈希表的理解

52 篇文章 0 订阅

简要:

主要是以两道题目的形式来学习一下这个两个知识点,前缀哈希表(Acwing第841题)和前缀字符串(Acwing第4312题)

相关题目:

解题思路:

相关代码1:
 

/*
    暴力法,不断地截取字符串,然后进行比较。时间复杂度较高,可能是n^2级别的。
*/
#include<iostream>
#include<string>
using namespace std;
int n,m;
string s;
int l1,r1,l2,r2;
int main(){
    cin>>n>>m>>s;
    while(m--){
        cin>>l1>>r1>>l2>>r2;
        string s1=s.substr(l1-1,r1-l1+1);
        string s2=s.substr(l2-1,r2-l2+1);
        if(s1==s2){
            cout<<"Yes"<<endl;
        }
        else{
            cout<<"No"<<endl;
        }
    }
    return 0;
}

相关代码2:

#include<iostream>
#include<string>
using namespace std;

typedef unsigned long long ULL;
int P=131;
//p[i]表示的是第i个字符的权重。
//h[i]表示的是前i个字符的哈希值。
// P = 131 或  13331 Q=2^64,在99%的情况下不会出现冲突
// 使用场景: 两个字符串的子串是否相同
//p[i]可以看成p^i次方
//ge()函数是为了取出区间内的哈希值。
int p[100001],h[100001];
ULL get(int l,int r){
    return h[r]-h[l-1]*p[r-l+1];
}

int n,m;
int l1,r1,l2,r2;
string s;
int main(){
    cin>>n>>m;
    cin>>s;
    s=' '+s;   //在字符串的首位加上一个空格。
    p[0]=1;  //p的0次方为1
    
    for(int i=1;i<=n;i++){
        p[i]=p[i-1]*P;   //算出每一位的权重,位数是从下标0开始的。
        h[i]=h[i-1]*P+s[i];
    }
    
    while(m--){
        cin>>l1>>r1>>l2>>r2;
        if(get(l1,r1)==get(l2,r2)){
            cout<<"Yes"<<endl;
        }
        else{
            cout<<"No"<<endl;
        }
        
    }
    return 0;
}


相关题目:

解题思路:

相关代码1:
 

/*
    暴力解法,时间复杂度可能会比较高。
*/
#include<iostream>
#include<string>
using namespace std;
int n,m,q;
string a,b;
int cnt;
int main(){
    cin>>n>>m>>q;
    cin>>a>>b;
    while(q--){
        int t1,t2;
        cin>>t1>>t2;
        string s=a.substr(t1-1,t2-t1+1);
        for(int i=0,j=b.size()-1;j<=s.size();i++,j++){
            string s1=s.substr(i,j-i+1);
            if(s1==b)
            cnt++;

        }
        cout<<cnt<<endl;
        cnt=0;
    }
    return 0;
}

相关代码2:

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int n,m,q;
string a,b;
int cnt;
int f[10001];
int main(){
    cin>>n>>m>>q;
    cin>>a>>b;
    reverse(a.begin(),a.end());
    a.push_back('0');
    reverse(a.begin(),a.end());
    reverse(b.begin(),b.end());
    a.push_back('0');
    reverse(b.begin(),b.end());
    for(int i=b.size();i<=a.size();i++){
        f[i]=f[i-1];
        string s1=a.substr(i-b.size()+1,m);
        if(s1==b){
            f[i]++;
        }
    }
    while(q--){
       int t1,t2;
       cin>>t1>>t2;
       t1+=m-1;
       if(t1>t2){
           cout<<0<<endl;
       }
       else{
            cout<<f[t2]-f[t1-1]<<endl;    
       }
        
    
    }
    return 0;
}

相关代码3:

/*
    运用前缀哈希表可以来解这道题。
*/
#include<iostream>
#include<string>
using namespace std;

int n,m,q;
string S,T;
typedef unsigned long long ULL;
ULL p[100001],h[100001];
const int P=131;
ULL get(int l,int r){
    return h[r]-h[l-1]*p[r-l+1];
}
int main(){
    cin>>n>>m>>q;
    cin>>S>>T;
    T=' '+T;
    S=' '+S;
    p[0]=1;
    for(int i=1;i<=n;i++){
        p[i]=p[i-1]*P;
        h[i]=h[i-1]*P+S[i];
    }
    
    int cmp=0;
    for(int i=1;i<=m;i++){
        cmp=cmp*P+T[i];
    }
    while(q--){
        int l,r;
        int cnt=0;
        scanf("%d%d",&l,&r);
        for(int i=l;i+m-1<=r;i++){
            if(get(i,i+m-1)==cmp){
                cnt++;
            }
        }
        cout<<cnt<<endl;
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值