[poj3450]Corporate Identity(后缀数组)

题意:多个字符串的最长公共子串。

解题关键:字符串的任何一个子串都是这个字符串的某个后缀的前缀。求A和B的最长公共子串等价于求A的后缀和B的后缀的最长公共前缀的最大值。

后缀数组的经典例题,连接在一起,二分长度,height数组遍历即可。

注意flag的问题,采用二分小于的方式,可能会出现有最优解但是flag为false的情况,下界需要-1,采用0,而采用等于的话,就不会出现,不过有些题会出现死循环。

还有因为多添加的符号一定不会加入vis数组,所以vis数组只需建立4000即可。

为什么两个字符串不需要二分?而多个字符串需要二分?因为 两个字符串可以直接判定height[i]是属于两个字符串的最大公共子串,而多个必须通过vis数组判定。

法一:

 1 #include<cstdlib>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<iostream>
 6 #include<cmath>
 7 using namespace std;
 8 const int N=800005;
 9 int r[N],id[N];
10 char tmp[220],ans[220];
11 bool vis[4200];
12 
13 int wa[N],wb[N],wv[N],wc[N],n,m;
14 bool cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
15 void make_sa(int *r,int *sa,int n,int m){
16     int i,j,p,*x=wa,*y=wb;
17     for(i=0;i<m;i++) wc[i]=0;
18     for(i=0;i<n;i++) wc[x[i]=r[i]]++;
19     for(i=1;i<m;i++) wc[i]+=wc[i-1];
20     for(i=n-1;i>=0;i--) sa[--wc[x[i]]]=i;
21     for(j=1,p=1;p<n;j*=2,m=p){
22         for(p=0,i=n-j;i<n;i++) y[p++]=i;
23         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
24         for(i=0;i<n;i++) wv[i]=x[y[i]];
25         for(i=0;i<m;i++) wc[i]=0;
26         for(i=0;i<n;i++) wc[wv[i]]++;
27         for(i=1;i<m;i++) wc[i]+=wc[i-1];
28         for(i=n-1;i>=0;i--) sa[--wc[wv[i]]]=y[i];
29         for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
30     }
31     return;
32 }
33 int rank1[N],height[N],sa[N];
34 void make_height(int *r,int *sa,int n){
35     int i,j,k=0;
36     for(i=1;i<=n;i++) rank1[sa[i]]=i;
37     for(i=0;i<n;height[rank1[i++]]=k)
38         for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++);
39     return;
40 }
41 
42 bool check(int x){
43     memset(vis,0,sizeof vis);
44     int cnt=0;
45     for(int i=2;i<=n;i++){
46         if(height[i]<x){
47             memset(vis,0,sizeof vis);
48             cnt=0;
49             continue;
50         }
51         if(!vis[id[sa[i-1]]]) vis[id[sa[i-1]]]=true,cnt++;
52         if(!vis[id[sa[i]]]) vis[id[sa[i]]]=true,cnt++;
53         if(cnt==m){
54             for(int j=0;j<x;j++) ans[j]=r[sa[i]+j]+'a'-1;ans[x]=0;
55             return true;
56         }
57     }
58     return false;
59 }
60 
61 bool erfen(int l,int r){
62     bool flag=false;
63     while(l<r){
64         int mid=(l+r+1)>>1;
65         if(check(mid)) l=mid,flag=true;
66         else r=mid-1;
67     }
68     return flag;
69 }
70 
71 int main() {
72     while(scanf("%d",&m)&&m){
73         n=0;
74         int temp=30;
75         for(int i=1;i<=m;i++){
76             scanf("%s",tmp);
77             int siz=strlen(tmp);
78             for(int j=0;j<siz;j++)    id[n]=i,r[n++]=tmp[j]-'a'+1;
79             id[n]=temp;
80             r[n++]=temp++;
81         }
82         r[n]=0;
83         make_sa(r,sa,n+1,4001);
84         make_height(r,sa,n);
85         bool f=erfen(0,200);//为什么0可以,1不可以 
86         if(f) printf("%s\n",ans);
87         else printf("IDENTITY LOST\n");
88     }
89 }

法二:

 1 #include<cstdlib>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<iostream>
 6 #include<cmath>
 7 using namespace std;
 8 const int N=800005;
 9 int r[N],id[N];
10 char tmp[220],ans[220];
11 bool vis[4200];
12 
13 int wa[N],wb[N],wv[N],wc[N],n,m;
14 bool cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
15 void make_sa(int *r,int *sa,int n,int m){
16     int i,j,p,*x=wa,*y=wb;
17     for(i=0;i<m;i++) wc[i]=0;
18     for(i=0;i<n;i++) wc[x[i]=r[i]]++;
19     for(i=1;i<m;i++) wc[i]+=wc[i-1];
20     for(i=n-1;i>=0;i--) sa[--wc[x[i]]]=i;
21     for(j=1,p=1;p<n;j*=2,m=p){
22         for(p=0,i=n-j;i<n;i++) y[p++]=i;
23         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
24         for(i=0;i<n;i++) wv[i]=x[y[i]];
25         for(i=0;i<m;i++) wc[i]=0;
26         for(i=0;i<n;i++) wc[wv[i]]++;
27         for(i=1;i<m;i++) wc[i]+=wc[i-1];
28         for(i=n-1;i>=0;i--) sa[--wc[wv[i]]]=y[i];
29         for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
30     }
31     return;
32 }
33 int rank1[N],height[N],sa[N];
34 void make_height(int *r,int *sa,int n){
35     int i,j,k=0;
36     for(i=1;i<=n;i++) rank1[sa[i]]=i;
37     for(i=0;i<n;height[rank1[i++]]=k)
38         for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++);
39     return;
40 }
41 
42 bool check(int x){
43     memset(vis,0,sizeof vis);
44     int cnt=0;
45     for(int i=2;i<=n;i++){
46         if(height[i]<x){
47             memset(vis,0,sizeof vis);
48             cnt=0;
49             continue;
50         }
51         if(!vis[id[sa[i-1]]]) vis[id[sa[i-1]]]=true,cnt++;
52         if(!vis[id[sa[i]]]) vis[id[sa[i]]]=true,cnt++;
53         if(cnt==m){
54             for(int j=0;j<x;j++) ans[j]=r[sa[i]+j]+'a'-1;ans[x]=0;
55             return true;
56         }
57     }
58     return false;
59 }
60 
61 bool erfen(int l,int r){
62     bool flag=false;
63     while(l<=r){
64         int mid=(l+r+1)>>1;
65         if(check(mid)) l=mid+1,flag=true;
66         else r=mid-1;
67     }
68     return flag;
69 }
70 
71 int main() {
72     while(scanf("%d",&m)&&m){
73         n=0;
74         int temp=30;
75         for(int i=1;i<=m;i++){
76             scanf("%s",tmp);
77             int siz=strlen(tmp);
78             for(int j=0;j<siz;j++)    id[n]=i,r[n++]=tmp[j]-'a'+1;
79             id[n]=temp;
80             r[n++]=temp++;
81         }
82         r[n]=0;
83         make_sa(r,sa,n+1,4001);
84         make_height(r,sa,n);
85         bool f=erfen(1,200);//为什么0可以,1不可以 
86         if(f) printf("%s\n",ans);
87         else printf("IDENTITY LOST\n");
88     }
89 }

 

dc3:依然注意是3倍的问题

  1 #include<cstdlib>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #include<iostream>
  6 #include<cmath>
  7 #define inf 0x3f3f3f3f
  8 typedef long long ll;
  9 using namespace std;
 10 const int N=800005;
 11 #define F(x) ((x)/3+((x)%3==1?0:tb))
 12 #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
 13 int wa[N],wb[N],wv[N],ws1[N];
 14 int c0(int *r,int a,int b){ return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2]; }
 15 int c12(int k,int *r,int a,int b){ 
 16     if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
 17     else return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];
 18 }
 19 void sort(int *r,int *a,int *b,int n,int m){
 20     int i;
 21     for(i=0;i<n;i++) wv[i]=r[a[i]];
 22     for(i=0;i<m;i++) ws1[i]=0;
 23     for(i=0;i<n;i++) ws1[wv[i]]++;
 24     for(i=1;i<m;i++) ws1[i]+=ws1[i-1];
 25     for(i=n-1;i>=0;i--) b[--ws1[wv[i]]]=a[i];
 26     return;
 27 }
 28 void dc3(int *r,int *sa,int n,int m){
 29     int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
 30     r[n]=r[n+1]=0;
 31     for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
 32     sort(r+2,wa,wb,tbc,m);
 33     sort(r+1,wb,wa,tbc,m);
 34     sort(r,wa,wb,tbc,m);
 35     for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
 36     rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
 37     if(p<tbc) dc3(rn,san,tbc,p);
 38     else for(i=0;i<tbc;i++) san[rn[i]]=i;
 39     for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
 40     if(n%3==1) wb[ta++]=n-1;
 41     sort(r,wb,wa,ta,m);
 42     for(i=0;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
 43     for(i=0,j=0,p=0;i<ta && j<tbc;p++)
 44     sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
 45     for(;i<ta;p++) sa[p]=wa[i++];
 46     for(;j<tbc;p++) sa[p]=wb[j++];
 47     return;
 48 }
 49 int rank1[N],height[N],sa[3*N];
 50 void make_height(int *r,int *sa,int n){
 51     int i,j,k=0;
 52     for(i=1;i<=n;i++) rank1[sa[i]]=i;
 53     for(i=0;i<n;height[rank1[i++]]=k)
 54         for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++);
 55     return;
 56 }
 57 int r[3*N],id[N],n,m;
 58 char tmp[220],ans[220];
 59 bool vis[4200];
 60 
 61 bool check(int x){
 62     memset(vis,0,sizeof vis);
 63     int cnt=0;
 64     for(int i=2;i<=n;i++){
 65         if(height[i]<x){
 66             memset(vis,0,sizeof vis);
 67             cnt=0;
 68             continue;
 69         }
 70         if(!vis[id[sa[i-1]]]) vis[id[sa[i-1]]]=true,cnt++;
 71         if(!vis[id[sa[i]]]) vis[id[sa[i]]]=true,cnt++;
 72         if(cnt==m){
 73             for(int j=0;j<x;j++) ans[j]=r[sa[i]+j]+'a'-1;ans[x]=0;
 74             return true;
 75         }
 76     }
 77     return false;
 78 }
 79 
 80 bool erfen(int l,int r){
 81     bool flag=false;
 82     while(l<r){
 83         int mid=(l+r+1)>>1;
 84         if(check(mid)) l=mid,flag=true;
 85         else r=mid-1;
 86     }
 87     return flag;
 88 }
 89 
 90 int main() {
 91     while(scanf("%d",&m)&&m){
 92         n=0;
 93         int temp=30;
 94         for(int i=1;i<=m;i++){
 95             scanf("%s",tmp);
 96             int siz=strlen(tmp);
 97             for(int j=0;j<siz;j++)    id[n]=i,r[n++]=tmp[j]-'a'+1;
 98             id[n]=temp;
 99             r[n++]=temp++;
100         }
101         r[n]=0;
102         dc3(r,sa,n+1,4001);
103         make_height(r,sa,n);
104         bool f=erfen(0,200);//为什么0可以,1不可以 
105         if(f) printf("%s\n",ans);
106         else printf("IDENTITY LOST\n");
107     }
108 }

 

posted @ 2017-09-22 16:53  Elpsywk  阅读(332)  评论(0编辑  收藏  举报