POJ-2774 Long Long Message 后缀数组

  题目链接:http://poj.org/problem?id=2774

  两个字符串的最长公共字串。

  求出height数组后直接二分答案就可以了,或者线性扫描一遍。

  1 //STATUS:C++_AC_594MS_4800KB

  2 #include<stdio.h>

  3 #include<stdlib.h>

  4 #include<string.h>

  5 #include<math.h>

  6 #include<iostream>

  7 #include<string>

  8 #include<algorithm>

  9 #include<vector>

 10 #include<queue>

 11 #include<stack>

 12 #include<map>

 13 using namespace std;

 14 #define LL __int64

 15 #define pii pair<int,int>

 16 #define mem(a,b) memset(a,b,sizeof(a))

 17 #define lson l,mid,rt<<1

 18 #define rson mid+1,r,rt<<1|1

 19 #define PI acos(-1.0)

 20 const int N=200010,INF=0x3f3f3f3f,MOD=10000,STA=8000010;

 21 //const LL LNF=0x3f3f3f3f3f3f3f3f;

 22 const double DNF=1e13;

 23 //

 24 inline int Max(int a,int b){return a>b?a:b;}

 25 inline int Min(int a,int b){return a<b?a:b;}

 26 void swap(int& a,int& b){int t=a;a=b;b=t;}

 27 void swap(LL& a,LL& b){LL t=a;a=b;b=t;}

 28 //

 29 

 30 char s[N/2];

 31 int num[N];

 32 int sa[N],t1[N],t2[N],c[N],rank[N],height[N];

 33 int n,m,len1,len2;

 34 

 35 void build_sa(int s[],int n,int m)

 36 {

 37     int i,k,p,*x=t1,*y=t2;

 38     //第一轮基数排序

 39     for(i=0;i<m;i++)c[i]=0;

 40     for(i=0;i<n;i++)c[x[i]=s[i]]++;

 41     for(i=1;i<m;i++)c[i]+=c[i-1];

 42     for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;

 43     for(k=1;k<=n;k<<=1){

 44         p=0;

 45         //直接利用sa数组排序第二关键字

 46         for(i=n-k;i<n;i++)y[p++]=i;

 47         for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;

 48         //基数排序第一关键字

 49         for(i=0;i<m;i++)c[i]=0;

 50         for(i=0;i<n;i++)c[x[y[i]]]++;

 51         for(i=1;i<m;i++)c[i]+=c[i-1];

 52         for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];

 53         //根据sa和x数组计算新的x数组

 54         swap(x,y);

 55         p=1;x[sa[0]]=0;

 56         for(i=1;i<n;i++)

 57             x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;

 58         if(p>=n)break;   //已经排好序,直接退出

 59         m=p;     //下次基数排序的最大值

 60     }

 61 }

 62 

 63 void getHeight(int s[],int n)

 64 {

 65     int i,j,k=0;

 66     for(i=0;i<=n;i++)rank[sa[i]]=i;

 67     for(i=0;i<n;i++){

 68         if(k)k--;

 69         j=sa[rank[i]-1];

 70         while(s[i+k]==s[j+k])k++;

 71         height[rank[i]]=k;

 72     }

 73 }

 74 

 75 int binary(int l,int r)

 76 {

 77     int i,j,mid,ok1,ok2,ret;

 78     while(l<=r){

 79         mid=(l+r)>>1;

 80         ok1=ok2=0;

 81         if(sa[1]<len1)ok1=1;

 82         else if(sa[1]>len1)ok2=1;

 83         for(i=2;i<=n;i++){

 84             if(height[i]<mid)ok1=ok2=0;

 85             if(sa[i]<len1)ok1=1;

 86             else if(sa[i]>len1)ok2=1;

 87             if(ok1 && ok2)break;

 88         }

 89         if(ok1 && ok2)ret=mid,l=mid+1;

 90         else r=mid-1;

 91     }

 92     return ret;

 93 }

 94 

 95 int main()

 96 {

 97  //   freopen("in.txt","r",stdin);

 98     int i,j;

 99     while(~scanf("%s",s) && s[0]!='#')

100     {

101         len1=strlen(s);

102         for(i=0;i<len1;i++)num[i]=s[i]-'a'+1;

103         num[len1]=27;

104         scanf("%s",s);

105         len2=strlen(s);

106         n=len1+len2+1;

107         for(i++,j=0;i<n;i++,j++)num[i]=s[j]-'a'+1;

108         num[n]=0;

109         m=28;

110         build_sa(num,n+1,m);

111         getHeight(num,n);

112 

113         printf("%d\n",binary(0,Min(len1,len2)));

114     }

115     return 0;

116 }

 

 

你可能感兴趣的:(message)