Description
Mushroom最近看上了一个漂亮妹纸。他选择一种非常经典的手段来表达自己的心意——写情书。考虑到自己的表达能力,Mushroom决定不手写情书。他从网上找到了两篇极佳的情书,打算选择其中共同的部分。另外,Mushroom还有个一个情敌Ertanis,此人也写了封情书给妹子。
Mushroom不希望自己的情书中完整的出现了情敌的情书。(这样抄袭的事情就暴露了)。
Mushroom把两封情书分别用字符串s1和s2来表示,Ertanis的情书用字符串s3来表示,他要截取的部分用字符串w表示。
需满足:
1、w是s1的子串
2、w是s2的子串
3、s3不是w的子串
4、w的长度应尽可能大
所谓子串是指:在字符串中连续的一段
【输入】
输入文件为girl.in
输入有三行,第一行为一个字符串s1第二行为一个字符串s2,
第三行为一个字符串s3。输入仅含小写字母,字符中间不含空格。
【输出】
输出文件为girl.out
输出仅有一行,为w的最大可能长度,如w不存在,则输出0。
【输入样例】
abcdef
abcf
bc
【输出样例】
2
【样例解释】
s1和s2的公共子串有abc,ab,bc,a,b,c,f,其中abc,bc包含子串bc不合法,所以最长的合法子串为ab。
【数据规模】
对于30%的数据:1<=s1、s2、s3的长度<=500
对于60%的数据:1<=s1、s2、s3的长度<=5000
对于100%的数据:1<=s1、s2的长度<=50000,1<=s3的长度<=10000
Input
输入有三行,第一行为一个字符串s1第二行为一个字符串s2,
第三行为一个字符串s3。输入仅含小写字母,字符中间不含空格。
Output
输出仅有一行,为w的最大可能长度,如w不存在,则输出0。
Sample Input
abcdef
abcf
bc
abcf
bc
Sample Output
2
【样例解释】
s1和s2的公共子串有abc,ab,bc,a,b,c,f,其中abc,bc包含子串bc不合法,所以最长的合法子串为ab。
【样例解释】
s1和s2的公共子串有abc,ab,bc,a,b,c,f,其中abc,bc包含子串bc不合法,所以最长的合法子串为ab。
HINT
对于100%的数据:1<=s1、s2的长度<=50000,1<=s3的长度<=10000
先把串S1和串S2拼接成串S(中间用’#’隔开),然后求一下height。
再对于S串每个后缀i,求出f[i]表示该串不包含S3串的最长前缀
然后就在一般的求最长公共子串的基础上把ans=max(ans,height[i])改成ans=max(ans,min(height[i],min(f[SA[i-1]],f[SA[i]])))就行了
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 100005 7 #define maxl 10005 8 using namespace std; 9 char s[maxn],s1[maxn],s2[maxn],s3[maxn]; 10 int n,m,l1,l2,tot,SA[maxn],height[maxn],rank[maxn],t1[maxn],t2[maxn],sum[maxn]; 11 int cnt,ans,pre[maxn],list[maxn],f[maxn]; 12 bool bo[maxn]; 13 void get_SA(){ 14 int *x=t1,*y=t2; 15 for (int i=1;i<=n;i++) sum[x[i]=s[i]]++; 16 for (int i=1;i<=m;i++) sum[i]+=sum[i-1]; 17 for (int i=n;i>=1;i--) SA[sum[x[i]]--]=i; 18 tot=0; 19 for (int len=1;tot<n;len<<=1,m=tot){ 20 tot=0; 21 for (int i=n-len+1;i<=n;i++) y[++tot]=i; 22 for (int i=1;i<=n;i++) if (SA[i]>len) y[++tot]=SA[i]-len; 23 for (int i=1;i<=m;i++) sum[i]=0; 24 for (int i=1;i<=n;i++) sum[x[y[i]]]++; 25 for (int i=1;i<=m;i++) sum[i]+=sum[i-1]; 26 for (int i=n;i>=1;i--) SA[sum[x[y[i]]]--]=y[i]; 27 swap(x,y),x[SA[1]]=tot=1; 28 for (int i=2;i<=n;i++){ 29 if (y[SA[i]]!=y[SA[i-1]]||y[SA[i]+len]!=y[SA[i-1]+len]) tot++; 30 x[SA[i]]=tot; 31 } 32 } 33 for (int i=1;i<=n;i++) rank[i]=x[i]; 34 } 35 void get_height(){ 36 for (int i=1,j=0;i<=n;i++){ 37 if (rank[i]==1) continue; 38 while (s[i+j]==s[SA[rank[i]-1]+j]) j++; 39 height[rank[i]]=j; 40 if (j) j--; 41 } 42 } 43 void prepare(){ 44 l2=strlen(s3+1)+1,s3[l2]='$'; 45 for (int i=2,j=0;i<=l2;i++){ 46 while (j&&s3[i]!=s3[j+1]) j=pre[j]; 47 if (s3[i]==s3[j+1]) j++; 48 pre[i]=j; 49 } 50 for (int i=1,j=0;i<=n;i++){ 51 while (j&&s[i]!=s3[j+1]) j=pre[j]; 52 if (s[i]==s3[j+1]) j++; 53 if (j==l2-1) list[++cnt]=i-l2+2; 54 } 55 for (int i=1,j=1;i<=n;i++){ 56 while (j<=cnt&&list[j]<i) j++; 57 if (j>cnt) f[i]=n-i+1; 58 else f[i]=list[j]-i+l2-2; 59 } 60 } 61 int main(){ 62 scanf("%s",s1+1),scanf("%s",s2+1),scanf("%s",s3+1); 63 for (int i=1;s1[i];i++) n++,s[i]=s1[i]; 64 l1=strlen(s1+1)+1,s[l1]='#',n++; 65 for (int i=1;s2[i];i++) n++,s[l1+i]=s2[i]; 66 m=123,get_SA(),get_height(); 67 prepare(); 68 for (int i=2;i<=n;i++) 69 if ((SA[i-1]<l1&&SA[i]>l1)||(SA[i-1]>l1&&SA[i]<l1)) 70 ans=max(ans,min(height[i],min(f[SA[i-1]],f[SA[i]]))); 71 printf("%d ",ans); 72 return 0; 73 }