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 }

 

 

posted @ 2013-04-24 19:39  zhsl  阅读(206)  评论(0编辑  收藏  举报