[BZOJ 3796]Mushroom追妹纸
[BZOJ 3796]Mushroom追妹纸
题目
Mushroom最近看上了一个漂亮妹纸。他选择一种非常经典的手段来表达自己的心意——写情书。考虑到自己的表达能力,Mushroom决定不手写情书。他从网上找到了两篇极佳的情书,打算选择其中共同的部分。另外,Mushroom还有个一个情敌Ertanis,此人也写了封情书给妹子。Mushroom不希望自己的情书中完整的出现了情敌的情书。(这样抄袭的事情就暴露了)。Mushroom把两封情书分别用字符串s1和s2来表示,Ertanis的情书用字符串s3来表示,他要截取的部分用字符串w表示。需满足:1、w是s1的子串2、w是s2的子串3、s3不是w的子串4、w的长度应尽可能大所谓子串是指:在字符串中连续的一段INPUT
输入文件为girl.in输入有三行,第一行为一个字符串s1第二行为一个字符串s2,第三行为一个字符串s3。输入仅含小写字母,字符中间不含空格。OUTPUT
输出文件为girl.out输出仅有一行,为w的最大可能长度,如w不存在,则输出0。SAMPLE
INPUT
abcdefabcfbcOUTPUT
2
解题报告
我不会说我一开始看错题废了我一个来小时的= =
首先我们可以把$s1$和$s2$中间加一个不会出现在该字符集中的字符将它俩接在一起,这个字符日常作用是分隔俩字符串
然后,我们对组合得到的字符串与$s3$跑$KMP$处理出每个匹配的串的位置
接下来就是极其简单的最长公共字串问题了,只要在判断时加一个是否被$KMP$标记过的条件即可
一定要读对题啊啊啊
s3不是w的子串!!!
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 char ch[4][150005]; 6 int len[4],bl[150005]; 7 char ran[4]={'!','@','#','$'}; 8 char s[150005]; 9 int n,m; 10 int t1[150005],t2[150005],t3[150005],buc[150005]; 11 int sa[150005],rank[150005],height[150005]; 12 int kp[150005]; 13 bool km[150005]; 14 inline void get_kp(){ 15 kp[0]=-1; 16 int i(0),j(-1); 17 while(i<len[3]){ 18 while(j!=-1&&ch[3][i]!=ch[3][j]) 19 j=kp[j]; 20 kp[++i]=++j; 21 } 22 } 23 inline void kmp(){ 24 int i(1),j(0); 25 while(i<=n){ 26 while(j!=-1&&s[i]!=ch[3][j]) 27 j=kp[j]; 28 ++i,++j; 29 if(j==len[3]) 30 km[i-len[3]]=1; 31 } 32 } 33 inline void Suffix(){ 34 int i,j,k(0),p(0),*x(t1),*y(t2),*t; 35 for(i=0;i<=m;++i)buc[i]=0; 36 for(i=1;i<=n;++i)++buc[x[i]=s[i]]; 37 for(i=1;i<=m;++i)buc[i]+=buc[i-1]; 38 for(i=n;i>=1;--i)sa[buc[x[i]]--]=i; 39 for(j=1;p<n;j<<=1,m=p){ 40 for(p=0,i=n-j+1;i<=n;++i)y[++p]=i; 41 for(i=1;i<=n;++i) 42 if(sa[i]>j) 43 y[++p]=sa[i]-j; 44 for(i=0;i<=m;++i)buc[i]=0; 45 for(i=1;i<=n;++i)t3[i]=x[y[i]]; 46 for(i=1;i<=n;++i)++buc[t3[i]]; 47 for(i=1;i<=m;++i)buc[i]+=buc[i-1]; 48 for(i=n;i>=1;--i)sa[buc[t3[i]]--]=y[i]; 49 for(t=x,x=y,y=t,x[sa[1]]=1,p=1,i=2;i<=n;++i) 50 x[sa[i]]=((y[sa[i]]==y[sa[i-1]])&&(y[sa[i]+j]==y[sa[i-1]+j]))?p:++p; 51 } 52 for(i=1;i<=n;++i)rank[sa[i]]=i; 53 for(i=1;i<=n;height[rank[i++]]=k) 54 for(k?k--:0,j=sa[rank[i]-1];s[i+k]==s[j+k];++k); 55 } 56 inline bool judge(int po,int x){//cout<<l<<' '<<r<<' '<<x<<endl; 57 if(x<len[3]) 58 return true; 59 for(int i=po,j=1;j<=x;++i,++j){ 60 if(km[i]&&j+len[3]-1<=x) 61 return false; 62 } 63 return true; 64 } 65 inline bool check(int x){//cout<<x<<endl; 66 int i,j,k; 67 bool flag[4]; 68 for(i=1;i<=n;++i){//cout<<i<<" "<<height[i]<<endl; 69 if(height[i]>=x){//cout<<endl; 70 for(j=i;height[j]>=x&&j<=n;++j); 71 --j; 72 // if(i==j) 73 // continue; 74 // cout<<i<<" "<<j<<endl<<endl; 75 memset(flag,0,sizeof(flag)); 76 for(k=i-1;k<=j;++k) 77 flag[bl[sa[k]]]=1; 78 if(flag[1]&&flag[2]&&judge(sa[i-1],x)) 79 return true; 80 // for(k=1;flag[k]&&k<=3;++k); 81 // if(k==3) 82 // return true; 83 i=j; 84 } 85 } 86 return false; 87 } 88 int main(){ 89 scanf("%s%s%s",ch[1],ch[2],ch[3]); 90 for(int i=1;i<=3;++i) 91 len[i]=strlen(ch[i]); 92 for(int i=1;i<=2;++i){ 93 for(int j=0;j<len[i];++j){ 94 s[++n]=ch[i][j]; 95 bl[n]=i;//cout<<n<<' '<<bl[n]<<endl; 96 } 97 s[++n]=ran[i]; 98 } 99 get_kp(); 100 kmp(); 101 m=130; 102 Suffix(); 103 int l(0),r(max(len[1],len[2])),ans(0); 104 while(l<=r){ 105 int mid((l+r)>>1); 106 if(check(mid)) 107 ans=mid,l=mid+1; 108 else 109 r=mid-1; 110 } 111 printf("%d",ans); 112 }