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 }