【poj3294-不小于k个字符串中最长公共子串】后缀数组

1.注意每两个串之间的连接符要不一样。

2.分组的时候要注意最后一组啊!又漏了!

3.开数组要考虑连接符的数量。100010是不够的至少要101000。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 using namespace std;
  6 
  7 const int N=102000;
  8 int n,cl,sl,ans,tt,c[N],tl[N],tr[N],al[N],ar[N],rk[N],Rs[N],sa[N],wr[N],y[N],h[N],st[N],ed[N];
  9 char s[1100];
 10 bool vis[1100];
 11 
 12 int minn(int x,int y){return x<y ? x:y;}
 13 
 14 
 15 void get_sa(int m)
 16 {
 17     for(int i=1;i<=cl;i++) rk[i]=c[i];
 18     for(int i=1;i<=m;i++) Rs[i]=0;
 19     for(int i=1;i<=cl;i++) Rs[rk[i]]++;
 20     for(int i=1;i<=m;i++) Rs[i]+=Rs[i-1];
 21     for(int i=cl;i>=1;i--) sa[Rs[rk[i]]--]=i;
 22     
 23     int ln=1,p=0;
 24     while(p<cl)
 25     {
 26         int k=0;
 27         for(int i=cl-ln+1;i<=cl;i++) y[++k]=i;
 28         for(int i=1;i<=cl;i++) if(sa[i]>ln) y[++k]=sa[i]-ln;
 29         
 30         for(int i=1;i<=cl;i++) wr[i]=rk[y[i]];
 31         for(int i=1;i<=m;i++) Rs[i]=0;
 32         for(int i=1;i<=cl;i++) Rs[wr[i]]++;
 33         for(int i=1;i<=m;i++) Rs[i]+=Rs[i-1];
 34         for(int i=cl;i>=1;i--) sa[Rs[wr[i]]--]=y[i];
 35         
 36         for(int i=1;i<=cl;i++) wr[i]=rk[i];
 37         for(int i=cl+1;i<=cl+ln;i++) wr[i]=0;
 38         p=1;rk[sa[1]]=1;
 39         for(int i=2;i<=cl;i++)
 40         {
 41             if(wr[sa[i]]!=wr[sa[i-1]] || wr[sa[i]+ln]!=wr[sa[i-1]+ln]) p++;
 42             rk[sa[i]]=p;
 43         }
 44         ln*=2,m=p;
 45     }
 46     sa[0]=0,rk[0]=0;
 47 }
 48 
 49 void get_h()
 50 {
 51     int k=0,j;
 52     for(int i=1;i<=cl;i++) if(rk[i]!=1)
 53     {
 54         j=sa[rk[i]-1];
 55         if(k) k--;
 56         while(c[j+k]==c[i+k] && j+k<=cl && i+k<=cl) k++;
 57         h[rk[i]]=k;
 58     }
 59     h[1]=0;
 60 }
 61 int idx(int x)
 62 {
 63     for(int i=1;i<=n;i++)
 64         if(st[i]<=x && x<=ed[i]) return i;
 65     return 0;
 66 }
 67 
 68 bool check(int k)
 69 {
 70     memset(vis,0,sizeof(vis));
 71     int now=cl;
 72     tt=0;
 73     for(int i=1;i<=cl;i++)
 74     {
 75         if(h[i]<k)
 76         {
 77             int cnt=0;
 78             for(int j=1;j<=n;j++) if(vis[j]) cnt++;
 79             if(cnt>(n/2)) tl[++tt]=sa[i-1],tr[tt]=tl[tt]+now-1; 
 80             memset(vis,0,sizeof(vis));
 81             now=cl-sa[i]+1;vis[idx(sa[i])]=1;
 82         }
 83         else
 84         {
 85             now=minn(now,h[i]);
 86             vis[idx(sa[i])]=1;
 87         }
 88     }
 89     int cnt=0;
 90     for(int j=1;j<=n;j++) if(vis[j]) cnt++;
 91     if(cnt>(n/2)) tl[++tt]=sa[cl-1],tr[tt]=tl[tt]+now-1; 
 92     if(tt) return 1;
 93     return 0;
 94 }
 95 
 96 int main()
 97 {
 98     freopen("a.in","r",stdin);
 99     int T=0;
100     while(1)
101     {
102         T++;
103         scanf("%d",&n);
104         if(n==0) return 0;
105         cl=0;ans=0;
106         for(int i=1;i<=n;i++)
107         {
108             scanf("%s",s+1);
109             sl=strlen(s+1);
110             if(i>1) c[++cl]=i;
111             st[i]=cl+1;
112             for(int j=1;j<=sl;j++) c[++cl]=s[j];
113             ed[i]=cl;
114         }
115         if(n==1) {printf("%c\n",c[1]);continue;}
116         get_sa(200);
117         get_h();
118         // for(int i=1;i<=cl;i++) printf("%c",c[i]);printf("\n");
119         // for(int i=1;i<=cl;i++) printf("%d ",sa[i]);printf("\n");
120         // for(int i=1;i<=cl;i++) printf("%d ",rk[i]);printf("\n");
121         // for(int i=1;i<=cl;i++) printf("%d ",h[i]);printf("\n");
122         int l=0,r=cl,mid;
123         while(l<r)
124         {
125             mid=(l+r+1)/2;
126             if(check(mid)) 
127             {
128                 l=mid;
129                 ans=tt;
130                 for(int i=1;i<=tt;i++) al[i]=tl[i],ar[i]=tr[i];
131             }
132             else r=mid-1;
133         }
134         if(T>1) printf("\n");
135         if(ans)
136         {
137             for(int i=1;i<=ans;i++)
138             {
139                 for(int j=al[i];j<=ar[i];j++) printf("%c",c[j]);
140                 printf("\n");
141             }
142         }
143         else printf("?\n");
144     }
145     return 0;
146 }

 

posted @ 2016-09-25 21:53  拦路雨偏似雪花  阅读(373)  评论(1编辑  收藏  举报