hdu 1403 Longest Common Substring (后缀数组模板题)

来源:互联网 发布:java 生成pdf 编辑:程序博客网 时间:2024/06/15 02:03

题意:

求两个串的最长公共子串。

题解:

后缀数组搞定。

#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<queue>#include<map>#include<set>using namespace std;#define B(x) (1<<(x))typedef long long ll;const int oo=0x3f3f3f3f;const ll OO=1LL<<61;const int MOD=10007;const int maxn=2000005;int rank[maxn],SA[maxn],length[maxn];char str[maxn];int res[maxn],cnt[maxn];void Swap(int*& a,int*& b){    int *temp;    temp=a;    a=b;    b=temp;}///cnt相当于基数排序的桶子,k1是第一关键字,k2是第二关键字void da(char s[],int len,int up){    int *k1=rank,*k2=length,*t=res;    ///基数排序    for(int i=0;i<up;i++)cnt[i]=0;    for(int i=0;i<len;i++)cnt[k1[i]=s[i]]++;    for(int i=1;i<up;i++)cnt[i]+=cnt[i-1];    for(int i=len-1;i>=0;i--)SA[--cnt[k1[i]]]=i;    for(int d=1,p=0;p<len;d<<=1){        for(int i=len-d;i<len;i++)k2[p++]=i;        for(int i=0;i<len;i++)if(SA[i]>=d)k2[p++]=SA[i]-d;        for(int i=0;i<len;i++)t[i]=k1[k2[i]];        ///基数排序        for(int i=0;i<up;i++)cnt[i]=0;        for(int i=0;i<len;i++)cnt[t[i]]++;        for(int i=1;i<up;i++)cnt[i]+=cnt[i-1];        for(int i=len-1;i>=0;i--)SA[--cnt[t[i]]]=k2[i];        Swap(k1,k2);        p=0;        k1[SA[0]]=p++;        for(int i=1;i<len;i++){            if(SA[i]+d<len&&SA[i-1]+d<len&&k2[SA[i]]==k2[SA[i-1]]&&k2[SA[i]+d]==k2[SA[i-1]+d])                k1[SA[i]]=p-1;            else                k1[SA[i]]=p++;        }        if(p>=len)return ;        up=p;        p=0;    }}void getLength(char s[],int len){    memset(rank,0,sizeof rank);    memset(length,0,sizeof length);    for(int i=0;i<len;i++)rank[SA[i]]=i;    //length[0]=0;    for(int i=0,p=0;i<len;i++){        int j=SA[rank[i]-1];        while(i+p<len&&j+p<len&&s[i+p]==s[j+p])p++;        length[rank[i]]=p;        if(p)p--;    }}int main(){    while(scanf("%s",str)!=EOF){        int len=strlen(str);        str[len]='#';        scanf("%s",str+len+1);        int L=strlen(str);        da(str,L,300);        getLength(str,L);        int ans=0;        for(int i=1;i<L;i++){            if(length[i]>ans){                if((SA[i]<len&&SA[i-1]>len)||(SA[i]>len&&SA[i-1]<len)){                    ans=length[i];                }            }        }        printf("%d\n",ans);    }    return 0;}//main/***/




0 0