POJ2774

题意:给定两个字符串,求两个串的最长公共子路。两个串的长度不超过100000。

算法:把两个串用一个连接符连接起来,然后求height[]和sa[],扫描height[],如果sa[i]和sa[i-1]分别在两个串中的最大hgight[]的值。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=200010;
 6 char c[100005],cc[100005];
 7 int s[maxn],sa[maxn],rank[maxn],height[maxn],saf[maxn],cs[maxn];
 8 int n,m,mid;
 9 void init()
10 {
11     scanf("%s",c);scanf("%s",cc);
12     int p=0;
13     for(int i=0;c[i];++i)s[++p]=c[i];++p;
14     mid=p;
15     for(int i=0;cc[i];++i)s[++p]=cc[i];
16     n=p;
17     s[0]=s[n+1]=-1;
18 }
19 void rsort()
20 {
21     for(int i=0;i<=m;++i)cs[i]=0;
22     for(int i=1;i<=n;++i)cs[rank[saf[i]]]++;
23     for(int i=1;i<=m;++i)cs[i]+=cs[i-1];
24     for(int i=n;i>=1;--i)sa[cs[rank[saf[i]]]--]=saf[i];
25 }
26 int cmp(int *f,int x,int y,int w)
27 {
28     return f[x]==f[y] && f[x+w]==f[y+w];
29 }
30 void suffix()
31 {
32     for(int i=1;i<=n;++i)rank[i]=s[i],saf[i]=i;
33     m=127;rsort();
34     for(int p=1,w=1,i;p<n;w<<=1,m=p)
35     {
36         for(i=n-w+1,p=0;i<=n;++i)saf[++p]=i;
37         for(i=1;i<=n;++i)if(sa[i]>w)saf[++p]=sa[i]-w;
38         rsort();swap(rank,saf);rank[sa[1]]=p=1;
39         for(i=2;i<=n;++i)rank[sa[i]]=cmp(saf,sa[i],sa[i-1],w)?p:++p;
40     }
41     int j,k=0;
42     for(int i=1;i<=n;height[rank[i++]]=k)
43         for(k=k?k-1:k,j=sa[rank[i]-1];s[i+k]==s[j+k];++k);
44 }
45 bool ind1(int x)
46 {
47     return x>=1 &&x<mid;
48 }
49 bool ind2(int x)
50 {
51     return x>mid && x<=n;
52 }
53 void work()
54 {
55     int ans=0;
56     for(int i=2;i<=n;++i)
57     if(height[i]>ans && ((ind1(sa[i]) && ind2(sa[i-1]))||(ind2(sa[i]) && ind1(sa[i-1]))))
58     ans=height[i];
59     cout<<ans;
60 }
61 int main()
62 {
63     init();
64     suffix();
65     work();
66     return 0;
67 }

 

posted on 2018-01-15 13:59  gryzy  阅读(188)  评论(0编辑  收藏  举报

导航