POJ1226 Substrings

后缀数组。

求多个字符串翻转与否中最长公共子串长。

二分答案,反过来多建一倍的字符串,二分时特判一下即可。

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[1005];
44 bool v[1005];
45 int tot,num;
46 bool check(int x,int n)
47 {
48     cnt=0;memset(v,0,sizeof(v));
49     for(int i=1;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)cnt++,v[bel[sa[i-1]]]=1;
55             if(!v[bel[sa[i]]])cnt++,v[bel[sa[i]]]=1;
56             if(cnt>=num)return 1;
57         }
58     }
59     return 0;
60 }
61 int main()
62 {
63     int t;
64     scanf("%d",&t);
65     while(t--)
66     {
67     scanf("%d",&num);
68     int len=0;int p=0;
69     for(int i=0;i<num;++i)
70     {
71         scanf("%s",s);
72         int n=strlen(s);
73         for(int j=0;j<n;++j)
74         {
75             r[len]=s[j];bel[len]=i;++len;
76         } 
77         r[len]=200+p;bel[len]=200+p;++len;++p;
78         for(int j=n-1;j>=0;--j)
79         {
80             r[len]=s[j];bel[len]=i;++len;
81         }
82         r[len]=200+p;bel[len]=200+p;++len;++p;
83     }
84     --len;r[len]=0;
85     da(r,sa,len+1,1000);
86     calcHeight(rank,sa,len);
87     int ans=0,l=1,r=len;
88     while(l<=r)
89     {
90         int mid=l+r>>1;
91         if(check(mid,len))ans=mid,l=mid+1;
92         else r=mid-1;
93     }
94     printf("%d\n",ans);
95     }
96     return 0;
97 }

 

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