求出一个串使得这个串是\(s1,s2\)的子串。串中不包含\(s3\)。

如果没有这个\(s3\)就可以二分答案,然后height小于二分值分一组。看看每组里是不是出现过\(s1,s2\)的后缀。判断就行。

然后有了\(s3\)之后,我们考虑改变一下height数组。

我们把\(s1s2\)拼在一起构成一个新串\(s\)。(中间隔一个#)

设\(s3\)的长度为\(len\)。

显然对于s中出现\(s3\)的起始位置\(x\)。\(height[rk[x]]\)要小于\(len\),\(height[rk[x-1]\)要小于\(len+1\),\(height[rk[x-2]]\)要小于\(len+2\)...

这样复杂度可能是\(O(n^2)\)的,其实我们只需要把初值为INF的\(g[x]\)设为\(len\),然后倒着做一遍\(g[i]=min(g[i],g[i+1])\),\(height[rk[i]]=min(height[rk[i]],g[i])\)就行。

所以我们需要知道\(s\)中\(s3\)的起始位置。这个用KMP解决。

然后愉快的二分就行了。

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=201010;
const int INF=1e9;
int sa[N],n,m,c[N],x[N],y[N],rk[N],height[N];
int n1,n2,n3,nxt[N],g[N],ans;
char s1[N],s2[N],s3[N],s[N];
void get_sa(){
for(int i=1;i<=n;i++)c[x[i]=s[i]]++;
for(int i=1;i<=m;i++)c[i]+=c[i-1];
for(int i=n;i>=1;i--)sa[c[x[i]]--]=i;
for(int k=1;k<=n;k<<=1){
int num=0;
for(int i=n-k+1;i<=n;i++)y[++num]=i;
for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k;
for(int i=1;i<=m;i++)c[i]=0;
for(int i=1;i<=n;i++)c[x[i]]++;
for(int i=1;i<=m;i++)c[i]+=c[i-1];
for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i],y[i]=0;
for(int i=1;i<=n;i++)swap(x[i],y[i]);
x[sa[1]]=1;num=1;
for(int i=2;i<=n;i++)
x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
if(num==n)break;
m=num;
}
}
void get_height(){
int k=0;
for(int i=1;i<=n;i++)rk[sa[i]]=i;
for(int i=1;i<=n;i++){
if(rk[i]==1)continue;
if(k)k--;
int j=sa[rk[i]-1];
while(i+k<=n&&j+k<=n&&s[j+k]==s[i+k])k++;
height[rk[i]]=k;
}
for(int i=1;i<=n;i++)height[rk[i]]=min(height[rk[i]],g[i]);
}
bool judge(int x){
bool flag1=false,flag2=false;
for(int i=1;i<=n;i++){
if(height[i]<x){
flag1=flag2=false;
if(sa[i]<=n1)flag1=true;
else flag2=true;
}
else{
if(sa[i]<=n1)flag1=true;
else flag2=true;
if(flag1&&flag2)return true;
}
}
return false;
}
int main(){
scanf("%s",s1+1);
scanf("%s",s2+1);
n1=strlen(s1+1);
n2=strlen(s2+1);
for(int i=1;i<=n1;i++)s[i]=s1[i];
s[n1+1]='#';
for(int i=1;i<=n2;i++)s[n1+i+1]=s2[i];
n=n1+n2+1;
scanf("%s",s3+1);
n3=strlen(s3+1);
for(int i=2,j=0;i<=n3;i++){
while(j&&s3[j+1]!=s3[i])j=nxt[j];
if(s3[j+1]==s3[i])j++;
nxt[i]=j;
}
for(int i=1;i<=n;i++)g[i]=INF;
for(int i=1,j=0;i<=n;i++){
while(j&&(s3[j+1]!=s[i]||j==n3))j=nxt[j];
if(s3[j+1]==s[i])j++;
if(j==n3)g[i-n3+1]=n3-1;
}
for(int i=n;i>=1;i--)g[i]=min(g[i],g[i+1]+1);
m=122;get_sa();get_height();
int l=1,r=n;
while(l<=r){
int mid=(l+r)>>1;
if(judge(mid)){
ans=mid;
l=mid+1;
}
else r=mid-1;
}
printf("%d",ans);
return 0;
}

BZOJ3796 Mushroom追妹纸(二分答案+后缀数组+KMP)的更多相关文章

  1. 【BZOJ3796】Mushroom追妹纸 二分+hash

    [BZOJ3796]Mushroom追妹纸 Description Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决 ...

  2. BZOJ3796 : Mushroom追妹纸

    将S1与S2用#号拼接在一起形成S串 将S3与S串跑KMP求出S3在S串中每次出现的位置l[i] 对于S串每个后缀i,求出f[i]表示该串不包含S3串的最长前缀 然后求出S串的后缀数组 先从小到大扫描 ...

  3. [BZOJ3796]Mushroom追妹纸:后缀自动机+KMP

    分析 这道题有个\(O(n)\)的后缀自动机做法,感觉很好理解就在这说一下. 先对\(s1\)和\(s2\)求最长公共子串,对于\(s2\)的每一个下标\(i\),求一个\(f[i]\)表示以\(s2 ...

  4. bzoj 3796: Mushroom追妹纸 AC自动机+后缀自动机+dp

    题目大意: 给定三个字符串s1,s2,s3,求一个字符串w满足: w是s1的子串 w是s2的子串 s3不是w的子串 w的长度应尽可能大 题解: 首先我们可以用AC自动机找出s3在s1,s2中出现的位置 ...

  5. BZOJ3796 Mushroom追妹纸 字符串 SA KMP

    原文链接https://www.cnblogs.com/zhouzhendong/p/9253173.html 题目传送门 - BZOJ3796 题意 找一个串 $w$ 满足: 1.$w$ 是 $s_ ...

  6. [BZOJ 3796]Mushroom追妹纸

    [BZOJ 3796]Mushroom追妹纸 题目 Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他 ...

  7. 【bzoj3796】Mushroom追妹纸

    Portal -->bzoj3796 Description 给出字符串s1.s2.s3,找出一个字符串w,满足: 1.w是s1的子串: 2.w是s2的子串: 3.s3不是w的子串. ​ 求w的 ...

  8. 【bzoj3796】Mushroom追妹纸 hash/sa+kmp+二分

    Description Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意--写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他从网上找到了两篇极佳的情书, ...

  9. 【bzoj3796】Mushroom追妹纸 Kmp+二分+Hash

    题目描述 给出字符串s1.s2.s3,找出一个字符串w,满足: 1.w是s1的子串: 2.w是s2的子串: 3.s3不是w的子串. 4.w的长度应尽可能大 求w的最大长度. 输入 输入有三行,第一行为 ...

随机推荐

  1. Lambda 表达式-即匿名函数

    拉姆达值(Lambda),希腊字母表示为Λ,指与真空的空间有关的能量或暗能量.   代表转换的常量.或者转换本身.   Lambda 表达式 Lambda 表达式”是一个匿名函数,可以包含表达式和语句 ...

  2. Eclipse安装不了AXIS2 Tool插件,总是找不到axis2 wizards的问题找到解决答案(转载)

    http://blog.csdn.net/downmoon/article/details/7309485 最近在学习axis2工作需要,google一搜,网上到处都是装axis2插件的.根据网上的直 ...

  3. BZOJ2179: FFT快速傅立叶 FFT实现高精度乘法

    Code: #include <cstdio> #include <algorithm> #include <cmath> #include <cstring ...

  4. html+css居中问题

    一.行级元素水平居中对齐(父元素设置 text-align:center) <div style="width: 200px; height: 100px;border: 1px so ...

  5. Facebook 运维内幕曝光:一人管理2万台服务器

    Facebook 运维内幕曝光:一人管理2万台服务器 oschina 发布于: 2013年11月23日 (29评) 分享到  新浪微博腾讯微博 收藏+32 11月30日 珠海 源创会,送U盘,先到先得 ...

  6. [置顶] 使用 maven 插件 maven-shade-plugin 对可执行 java 工程及其全部依赖 jar 进行打包

    作者:chenzhou123520 出处:http://chenzhou123520.iteye.com/blog/1706242 使用 maven 插件 maven-shade-plugin 对 j ...

  7. linux 源码包安装拾遗

    源码包安装和apt-get/yum的区别 安装前的区别:概念上的区别 rpm和dpkg包是经过编译过的包,并且其安装位置由厂商说了算,厂商觉得安装在哪里合适,就会装在哪里,而源码包则是没有经过编译的文 ...

  8. 如何成为资深的python专家

    相信很多人有这种感受,python很简单,几天就学会了:做了一段时间就觉得python没什么好玩的,就这样. 一种语言有火这么久,必有它存在的道理. 第一.我们要相信她,她就像你的新女朋友一样,她会给 ...

  9. java--web学习总结<转>

    http://www.cnblogs.com/xdp-gacl/p/3729033.html

  10. 洛谷 P2932 [USACO09JAN]地震造成的破坏Earthquake Damage

    P2932 [USACO09JAN]地震造成的破坏Earthquake Damage 题目描述 Wisconsin has had an earthquake that has struck Farm ...