• BNU 34990 Justice String (hash+二分求LCP)


    思路:枚举第一个字符串的位置,然后枚举最长公共前缀的长度,时间即会下降……

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<set>
    #include<cmath>
    #include<bitset>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson i<<1,l,mid
    #define rson i<<1|1,mid+1,r
    #define llson j<<1,l,mid
    #define rrson j<<1|1,mid+1,r
    #define seed 131
    #define INF 0x7fffffff
    #define maxn 200105
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    ull base[maxn],hash1[maxn],hash2[maxn];
    int n,m;
    char s1[maxn],s2[maxn];
    int judge(int i,int j)
    {
        int l=0,r=m,mid,ans=0;
        while(l<=r)
        {
            mid=(l+r)>>1;//二分最长公共前缀
            if(i+mid-1>n||j+mid-1>m)
            {
                r=mid-1;
                continue;
            }
            ull a=hash1[i+mid-1]-hash1[i-1]*base[mid];
            ull b=hash2[j+mid-1]-hash2[j-1]*base[mid];
            if(a==b) l=mid+1,ans=mid;
            else r=mid-1;
        }
        return ans;
    }
    int main()
    {
        freopen("1.txt","r",stdin);
        int i,t,ii=1,flag;
        scanf("%d",&t);
        for(i=1,base[0]=1;i<maxn;i++)
            base[i]=base[i-1]*seed;
        while(t--)
        {
            scanf("%s%s",s1,s2);
            n=strlen(s1),m=strlen(s2);
            for(i=1,hash1[0]=0;i<=n;i++)
                hash1[i]=hash1[i-1]*seed+s1[i-1]-'a'+1;
            for(i=1,hash2[0]=0;i<=m;i++)
                hash2[i]=hash2[i-1]*seed+s2[i-1]-'a'+1;
            for(i=1;i<=n-m+1;i++)//枚举第一个字符串的起始位置
            {
                int j=1,k=i,cnt=0;
                flag=0;
                while(k<=n)
                {
                    int len=judge(k,j);//两个位置的最长公共前缀
                    k+=len+1;
                    j+=len+1;
                    cnt++;
                    if(cnt==2)
                    {
                        if(j>m||j+judge(k,j)>m) flag=1;
                        break;
                    }
                    if(j>m) {flag=1;break;}
                }
                if(flag) break;
            }
            if(flag) printf("Case #%d: %d
    ",ii++,i-1);
            else printf("Case #%d: -1
    ",ii++);
        }
        return 0;
    }
    


  • 相关阅读:
    大道至简 第一章 读后随笔
    大道至简 第二章 读后随笔
    动手动脑及实验性练习总结
    大道至简 第三章 阅读心得
    课程作业01 相加运算
    JS函数与BOM
    设备像素,设备独立像素,CSS像素
    斐波那契数列
    JS基础与循环
    吴requests类库 作业总结
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/7224934.html
Copyright © 2020-2023  润新知