[BZOJ 3796]Mushroom追妹纸

Posted Mafia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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

abcdef
abcf
bc

OUTPUT

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 }
View Code

 

以上是关于[BZOJ 3796]Mushroom追妹纸的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3796 Mushroom追妹纸——后缀数组

bzoj 3796 Mushroom追妹纸 —— 后缀数组

2018.7.31 Noip2018模拟测试赛(十六)

bzoj3796

新来的长腿程序猿妹纸

(最短路)17bupt新生赛——F. ch追妹