ZOJ4030 JUMPin' JUMP UP!!!(哈希+最小循环节)

xz=zy

其实对应的就是把x的某一段前缀减下来贴到后面或者把y的某一段前缀贴下来到前面

如果相等则可以,这点可以在纸上模拟。因为y一直在变,所以我们考虑预处理x

对比字符串是否相等,使用哈希即可,本题使用了双哈希避免被卡。

我们关注到,当我们求得最小能够剪切成功的段时,答案并不是只有这个,因为如果串中有循环节,那么我们加上循环节长度也能获得新的答案。因此我们继续考虑预处理最小循环节。

这样这道题就做完了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
char s[N],t[N];
const int mod1=1e9+7;
const int mod2=1e9+9;
const int base=131;
map<ll,int> m1;
int n,m,q;
int nxt[N];
ll p1[N],p2[N];
struct node{
    ll l,r;
}h[N];
int pos[N];
void Hash(){
    p1[0]=1,p2[0]=1;
    for(int i=1;i<=n;i++){
        p1[i]=p1[i-1]*base%mod1;
        p2[i]=p2[i-1]*base%mod2;
        h[i].l=(h[i-1].l*base%mod1+(s[i]-'0'))%mod1;
        h[i].r=(h[i-1].r*base%mod2+(s[i]-'0'))%mod2;
    }
}
ll get(int l,int r){
    ll h1=(h[r].l-(h[l-1].l*p1[r-l+1]%mod1)+mod1)%mod1;
    ll h2=(h[r].r-(h[l-1].r*p2[r-l+1]%mod2)+mod2)%mod2;
    return h1+h2;
}
int main(){
    int T;
    cin>>T;
    while(T--){
        int i;
        scanf("%d%d%d",&n,&m,&q);
        scanf("%s",s+1);
        scanf("%s",t+1);
        m1.clear();
        nxt[0]=-1;
        int cnt=0;
        for(int i=1;i<=m;i++){
            int p=nxt[i-1];
            while(p>=0&&t[p+1]!=t[i]) p=nxt[p];
            nxt[i]=p+1;
        }
        int len=m-nxt[m];
        if(nxt[m]*2<m) len=m;
        Hash();
        node x={0,0};
        for(i=1;i<=m;i++){
            ll h1=(x.l*base%mod1+(t[i]-'0')+mod1)%mod1;
            ll h2=(x.r*base%mod2+(t[i]-'0')+mod2)%mod2;
            x={h1,h2};
        }
        for(i=1;i<=m;i++){
            ll h1=(x.l*base%mod1+(t[i]-'0')-(ll)(t[i]-'0')*p1[m]%mod1+mod1)%mod1;
            ll h2=(x.r*base%mod2+(t[i]-'0')-(ll)(t[i]-'0')*p2[m]%mod2+mod2)%mod2;
            x={h1,h2};
            if(!m1[h1+h2]){
                m1[h1+h2]=++cnt;
                pos[cnt]=i;
            }
        }
        while(q--){
            ll x,y;
            scanf("%lld%lld",&x,&y);
            auto tmp=get(x,x+m-1);
            if(!m1[tmp]){
                printf("0
");
            }
            else{
                int d=m1[tmp];
                printf("%lld
",(ll)(y-pos[d])/len+1);
            }
        }
    }
    return 0;
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/13758239.html