[题目来源]:South Central USA 2006
[关键字]:字符串
[题目大意]:找出给所有字符串的最长公共字串。
//=====================================================================================================
[分析]:暴力枚举+KMP。最近刚学了后缀数组,发现用它也可以解出这道题,所以就试了试,但说实话很失败……输出错了还以为算法错了白调了半天,后缀数组做这道题代码很长(也许是我写坏了),基本思路就是连在一起然后二分答案对后缀数组分组。
[代码]:
1 var
2 tc, n: longint;
3 p: array[0..100] of longint;
4 w: array[0..100] of string;
5
6 procedure init;
7 var
8 i: longint;
9 begin
10 readln(n);
11 for i := 1 to n do
12 readln(w[i]);
13 //for i := 1 to n do writeln(w[i]);
14 end;
15
16 function KMP(s1, s2: string):boolean;
17 var
18 t1, t2, k, i: longint;
19 begin
20 t1 := length(s1);
21 t2 := length(s2);
22 fillchar(p,sizeof(p),0);
23 k := 0;
24 p[1] := 0;
25 for i := 2 to t2 do
26 begin
27 while (k > 0) and (s2[i] <> s2[k+1]) do k := p[k];
28 if s2[i] = s2[k+1] then inc(k);
29 p[i] := k;
30 end;
31 k := 0;
32 for i := 1 to t1 do
33 begin
34 while (k > 0) and (s2[k+1] <> s1[i]) do k := p[k];
35 if s2[k+1] = s1[i] then inc(k);
36 if k = t2 then exit(true);
37 end;
38 exit(false);
39 end;
40
41 procedure work;
42 var
43 len, i, j: longint;
44 s, ans: string;
45 f: boolean;
46 begin
47 ans := '';
48 for len := 60 downto 2 do
49 begin
50 for i := 1 to 60-len+1 do
51 begin
52 f := true;
53 s := copy(w[1],i,len);
54 //writeln(s);
55 for j := 2 to n do
56 if not KMP(w[j],s) then
57 begin f := false; break; end;
58 if f then
59 if (ans = '') or (ans > s) then ans := s;
60 end;
61 if ans <> '' then break;
62 end;
63 // writeln(ans);
64 if ans = '' then writeln('no significant commonalities') else writeln(ans);
65 end;
66
67 begin
68 // assign();reset(input);
69 // assign(output,'d:\1.out');rewrite(output);
70 readln(tc);
71 while tc <> 0 do
72 begin
73 init;
74 work;
75 //readln(w[1]);
76 //readln(w[2]);
77 //writeln(KMP(w[2],w[1]));
78 dec(tc);
79 end;
80 // close(output);
81 end.
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<set>
#include<string>
using namespace std;
const int MAXL=70;
const int MAXN=800;
int n,test,x,df;
int top[MAXN],r[MAXN],height[MAXN],sa[MAXN],temp[MAXN];
int s[MAXN],belong[MAXN];
char s1[MAXL],q[MAXL];
bool v[MAXL];
set<string> p;
void Make()
{
int i,j,m,len;
memset(top,0,sizeof(top));
m=n<256?256:n;
for (i=0;i<n;++i) ++top[r[i]=s[i]&0xff];
for (i=1;i<m;++i) top[i]+=top[i-1];
for (i=0;i<n;++i) sa[--top[r[i]]]=i;
for (len=1;len<n;len<<=1)
{
for (i=0;i<n;++i)
{
j=sa[i]-len;
if (j<0) j+=n;
temp[top[r[j]]++]=j;
}
sa[temp[top[0]=0]]=j=0;
for (i=1;i<n;++i)
{
if (r[temp[i]]!=r[temp[i-1]] ||
r[temp[i]+len]!=r[temp[i-1]+len])
top[++j]=i;
sa[temp[i]]=j;
}
memcpy(r,sa,sizeof(sa));
memcpy(sa,temp,sizeof(sa));
if (j>=n-1) break;
}
}
void Lcp()
{
int i,j,k;
for (j=r[height[i=k=0]=0];i<n-1;++i,++k)
while (k>=0 && s[i]!=s[sa[j-1]+k])
height[j]=k--,j=r[sa[j]+1];
}
bool Judge(int limit)
{
int i,d=0;
memset(v,0,sizeof(v));
v[0]=1;
if (!v[belong[sa[0]]]) ++d;
v[belong[sa[0]]]=1;
for (i=1;i<n;++i)
{
if (height[i]<limit)
{
d=0;
memset(v,0,sizeof(v));
v[0]=1;
}
if (!v[belong[sa[i]]]) ++d;
v[belong[sa[i]]]=1;
if (d>=x) return 1;
}
return 0;
}
void Print(int limit)
{
int i,d=0,j,len;
memset(v,0,sizeof(v));
v[0]=1;
if (!v[belong[sa[i]]]) ++d;
v[belong[sa[0]]]=1;
for (int i=1;i<n;++i)
{
if (height[i]<limit)
{
d=0;
memset(v,0,sizeof(v));
v[0]=1;
}
if (!v[belong[sa[i]]]) ++d;
v[belong[sa[i]]]=1;
if (d>=x)
{
len=0;
memset(q,0,sizeof(q));
for (int j=sa[i];j<sa[i]+limit;++j)
q[len++]=s[j];
p.insert(q);
}
}
}
void Solve()
{
int l=1,r=60,mid,ans=0;
while (l<=r)
{
mid=(l+r)/2;
if (Judge(mid)) ans=mid,l=mid+1; else r=mid-1;
}
if (ans<3) printf("no significant commonalities\n"); else printf(""),Print(ans),cout<<*p.begin()<<endl;
}
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d",&test);
while (test--)
{
n=df=0;
p.clear();
scanf("%d",&x);
for (int i=1;i<=x;++i)
{
scanf("%s",s1);
int len=strlen(s1);
//printf("%d\n",len);
for (int j=0;j<len;++j)
s[n++]=(int)s1[j],belong[n-1]=i;
s[n++]=++df,belong[n-1]=0;
}
s[n-1]=0;
Make();
Lcp();
//printf("%d\n",n);
//for (int i=0;i<n;++i) printf("%d ",height[i]);
//printf("\n");
Solve();
}
return 0;
}