POJ3450 Corporate Identity

后缀数组。

解决多个字符串的最长公共子串。

采用对长度的二分,将子串按height分组,每次判断是否在每个字符串中都出现过。

复杂度O(NlogN)

By:大奕哥

  1 #include<cstring>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 #include<iostream>
  6 #define rank fank
  7 using namespace std;
  8 const int N=1000005;
  9 int r[N],wa[N],wb[N],wv[N],wu[N],sa[N],rank[N],height[N],bel[N],cnt;
 10 int cmp(int *r,int a,int b,int l)
 11 {
 12     return r[a]==r[b]&&r[a+l]==r[b+l];
 13 }
 14 void da(int *r,int *sa,int n,int m)
 15 {
 16     int i,j,p;int *x=wa,*y=wb;
 17     for(i=0;i<m;++i)wu[i]=0;
 18     for(i=0;i<n;++i)wu[x[i]=r[i]]++;
 19     for(i=1;i<m;++i)wu[i]+=wu[i-1];
 20     for(i=n-1;i>=0;--i)sa[--wu[x[i]]]=i;
 21     for(j=1,p=1;p<n;j<<=1,m=p)
 22     {
 23         for(p=0,i=n-j;i<n;++i)y[p++]=i;
 24         for(i=0;i<n;++i)if(sa[i]>=j)y[p++]=sa[i]-j;
 25         for(i=0;i<n;++i)wv[i]=x[y[i]];
 26         for(i=0;i<m;++i)wu[i]=0;
 27         for(i=0;i<n;++i)wu[wv[i]]++;
 28         for(i=0;i<m;++i)wu[i]+=wu[i-1];
 29         for(i=n-1;i>=0;--i)sa[--wu[wv[i]]]=y[i];
 30         for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;++i)
 31         x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
 32     }
 33     return;
 34 }
 35 void calcHeight(int *rank,int *sa,int n)
 36 {
 37     int i,j,k=0;
 38     for(i=1;i<=n;++i)rank[sa[i]]=i;
 39     for(i=0;i<n;height[rank[i++]]=k)
 40         for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];++k);
 41     return ;
 42 }
 43 char s[N],ans[N];
 44 bool v[4005];
 45 int tot,num;
 46 bool check(int x,int n)
 47 {
 48     memset(v,0,sizeof(v));
 49     for(int i=2;i<=n;++i)
 50     {
 51         if(height[i]<x){cnt=0;memset(v,0,sizeof(v));}
 52         else
 53         {
 54             if(v[bel[sa[i-1]]]==0){
 55                 cnt++;v[bel[sa[i-1]]]=1;
 56             }
 57             if(v[bel[sa[i]]]==0){
 58                 cnt++;v[bel[sa[i]]]=1;
 59             }
 60             if(cnt==num)
 61             {
 62                 for(int j=0;j<x;++j)
 63                 ans[j]=r[sa[i]+j];
 64                 ans[x]='\0';
 65                 return 1;
 66             }
 67         }
 68     }
 69     return 0;
 70 }
 71 int main()
 72 {
 73     while(~scanf("%d",&num)&&num)
 74     {
 75     int len=0;
 76     for(int i=0;i<num;++i)
 77     {
 78         scanf("%s",s);
 79         int n=strlen(s);
 80         for(int j=0;j<n;++j)
 81         {
 82             r[len]=s[j];bel[len]=i;++len; 
 83         } 
 84         r[len]=200+i;bel[len]=200+i;++len;
 85     }
 86     --len;r[len]=0;
 87     da(r,sa,len+1,5000);
 88     calcHeight(rank,sa,len);
 89     int as=0,l=1,r=len;
 90     while(l<=r)
 91     {
 92         int mid=l+r>>1;
 93         if(check(mid,len))as=1,l=mid+1;
 94         else r=mid-1;
 95     }
 96     if(as)printf("%s\n",ans);
 97     else
 98     printf("IDENTITY LOST\n");
 99     }
100     return 0;
101 }

Ps:wa了好多遍,因为插进去的ascII码值没有选好,附一张ascII表。

posted @ 2018-01-05 18:11  大奕哥&VANE  阅读(230)  评论(0编辑  收藏  举报