1. 程式人生 > >BNU 34990 Justice String (hash+二分求LCP)

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

urn ont 最長公共前綴 inf memset return mem 第一個字符 bnu

思路:枚舉第一個字符串的位置,然後枚舉最長公共前綴的長度,時間即會下降……

#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\n",ii++,i-1);
        else printf("Case #%d: -1\n",ii++);
    }
    return 0;
}


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