zoukankan      html  css  js  c++  java
  • 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
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    Linux-netstat
    API接口防止参数篡改和重放攻击
    Java中遍历Map的几种方式
    Java泛型中的标记符含义
    Iterator 和 for...of 循环
    Promise 对象
    Reflect
    正则要求密码长度最少12位,包含至少1个特殊字符,2个数字,2个大写字母和一些小写字母。
    一个JS正则表达式,一个正实数,整数部分最多11位 小数部分最多 8位
    java阿里云短信发送配置
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13758239.html
Copyright © 2011-2022 走看看