SPOJ220 Relevant Phrases of Annihilation

http://www.spoj.com/problems/PHRASES/

题意:给n个串,求n个串里面都有2个不重叠的最长的字串长度。

思路:二分答案,然后就可以嘿嘿嘿

PS:辣鸡题目毁我青春,一开始二分的时候ans没有赋初值为0,结果没答案的时候就会输出奇怪的数字T_T,其实主要还是怪我不小心。。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 int len,num[500005],ws[500005],wv[500005],wa[500005],wb[500005],h[500005],sa[500005],rank[500005];
 7 int f[500005][2],N,b[500005];
 8 char s[500005];
 9 int read(){
10     int t=0,f=1;char ch=getchar();
11     while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
12     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
13     return t*f;
14 }
15 bool cmp(int *r,int a,int b,int l){
16     return r[a]==r[b]&&r[a+l]==r[b+l];
17 }
18 void da(int *r,int *sa,int n,int m){
19     int *t,*x=wa,*y=wb,i,j,k,p;
20     for (i=0;i<m;i++) ws[i]=0;
21     for (i=0;i<n;i++) x[i]=r[i];
22     for (i=0;i<n;i++) ws[x[i]]++;
23     for (i=1;i<m;i++) ws[i]+=ws[i-1];
24     for (i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
25     for (j=1,p=1;p<n;j*=2,m=p){
26         for (p=0,i=n-j;i<n;i++) y[p++]=i;
27         for (i=0;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j;
28         for (i=0;i<m;i++) ws[i]=0;
29         for (i=0;i<n;i++) wv[i]=x[y[i]];
30         for (i=0;i<n;i++) ws[wv[i]]++;
31         for (i=1;i<m;i++) ws[i]+=ws[i-1];
32         for (i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
33         for (t=x,x=y,y=t,i=1,x[sa[0]]=0,p=1;i<n;i++){
34             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
35         }
36     }
37 }
38 void cal(int *r,int n){
39     int i,j,k=0;
40     for (int i=1;i<=n;i++) rank[sa[i]]=i;
41     for (int i=0;i<n;h[rank[i++]]=k){
42         for (k?k--:0,j=sa[rank[i]-1];r[j+k]==r[i+k];k++);
43     }
44 }
45 bool check(int mid){
46     int l,r;
47     for (int i=1;i<=len;i++){
48         l=i;
49         while (l<=len&&h[l]<mid) l++;
50         r=l;
51         while (r<=len&&h[r]>=mid) r++;
52         for (int j=1;j<=N;j++) f[j][0]=0x3f3f3f3f,f[j][1]=-0x3f3f3f3f;
53         for (int j=l-1;j<=r-1;j++){
54             int k=b[sa[j]];
55             if (k==N+1) continue;
56             f[k][0]=std::min(f[k][0],sa[j]);
57             f[k][1]=std::max(f[k][1],sa[j]);
58         }
59         int j=0;
60         for (j=1;j<=N;j++){
61             if (f[j][0]==0x3f3f3f3f) break;
62             if (f[j][1]-f[j][0]<mid) break;
63         }
64         if (j>N) return 1;
65         i=r;
66     }
67     return 0;
68 }
69 void solve(){
70     int l=1,r=20000,ans=0;
71     while (l<=r){
72         int mid=(l+r)>>1;
73         if (check(mid)) ans=mid,l=mid+1;
74         else r=mid-1;
75     }
76     printf("%d ",ans);
77 }
78 int main(){
79     int T=read();
80     while (T--){
81         len=0;
82         int n=read();
83         for (int i=1;i<=n;i++){
84             scanf("%s",s+1);
85             int Len=strlen(s+1);
86             for (int j=1;j<=Len;j++)
87              num[len]=s[j],b[len++]=i;
88             if (i<n) num[len]=290+i,b[len++]=n+1; 
89         }
90         num[len]=0;b[len]=n+1;
91         da(num,sa,len+1,310);
92         cal(num,len);
93         N=n;
94         solve();
95     }
96 }

 

posted @ 2016-07-02 23:11  GFY  阅读(253)  评论(0编辑  收藏  举报