【题目分析】
用height数组RMQ的性质去求最长的公共子串。
要求sa[i]和sa[i-1]必须在两个串中,然后取height的MAX。
利用中间的字符来连接两个字符串的思想很巧妙,记得最后还需要空一个位置避免冲突。
【代码】
#include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define maxn 200005 #define inf 0x3f3f3f3f #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) void Finout() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); #endif } int Getint() { int x=0,f=1; char ch=getchar(); while (ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();} while (ch>=‘0‘&&ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();} return x*f; } int tot=0,l1,l2; char s1[maxn],s2[maxn]; struct Suf_Arr{ int s[maxn<<1],l; int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; int sa[maxn],rank[maxn],height[maxn]; int cmp(int *r,int a,int b,int l) {return r[a]==r[b]&&r[a+l]==r[b+l];} void getsa(int n,int m) { int i,j,p,*x=wa,*y=wb,*t; for (i=0;i<m;++i) ws[i]=0; for (i=0;i<n;++i) ws[x[i]=s[i]]++; for (i=1;i<m;++i) ws[i]+=ws[i-1]; for (i=n-1;i>=0;--i) sa[--ws[x[i]]]=i; for (j=1,p=1;p<n;j*=2,m=p) { for (p=0,i=n-j;i<n;++i) y[p++]=i; for (i=0;i<n;++i) if (sa[i]>=j) y[p++]=sa[i]-j; for (i=0;i<n;++i) wv[i]=x[y[i]]; for (i=0;i<m;++i) ws[i]=0; for (i=0;i<n;++i) ws[wv[i]]++; for (i=1;i<m;++i) ws[i]+=ws[i-1]; for (i=n-1;i>=0;--i) sa[--ws[wv[i]]]=y[i]; for (t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;++i) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } } void gethi(int n) { int i,j,k=0; for (i=1;i<=n;++i) rank[sa[i]]=i; for (int i=0;i<n;height[rank[i++]]=k) for (k?k--:0,j=sa[rank[i]-1];s[i+k]==s[j+k];k++); } void build() { getsa(l+2,30); // for (int i=0;i<=l;++i) cout<<sa[i]<<" "; cout<<endl; gethi(l+1); } void solve() { int maxx=0; for(int i=2;i<l;++i) if (height[i]>maxx) { if (0<=sa[i-1]&&sa[i-1]<l1&&l1<sa[i]) maxx=height[i]; if (0<=sa[i]&&sa[i]<l1&&l1<sa[i-1]) maxx=height[i]; } printf("%d\n",maxx); } }arr; int main() { Finout(); scanf("%s",s1); scanf("%s",s2); l1=strlen(s1); l2=strlen(s2); arr.l=l1+l2+1; for (int i=0;i<l1;++i) arr.s[i]=s1[i]-‘a‘+1; for (int i=0;i<l2;++i) arr.s[i+l1+1]=s2[i]-‘a‘+1; arr.s[l1+l2+1]=0; arr.s[l1]=28; // printf("len is %d\n",arr.l); // for (int i=0;i<=arr.l;++i) cout<<(char)(arr.s[i]+‘a‘-1); cout<<endl; arr.build(); arr.solve(); }
时间: 2024-10-20 07:46:04