Description

Mushroom最近看上了一个漂亮妹纸。他选择一种非常经典的手段来表达自己的心意——写情书。考虑到自己的表达能力,Mushroom决定不手写情书。他从网上找到了两篇极佳的情书,打算选择其中共同的部分。另外,Mushroom还有个一个情敌Ertanis,此人也写了封情书给妹子。

Mushroom不希望自己的情书中完整的出现了情敌的情书。(这样抄袭的事情就暴露了)。

Mushroom把两封情书分别用字符串s1和s2来表示,Ertanis的情书用字符串s3来表示,他要截取的部分用字符串w表示。

需满足:

1、w是s1的子串

2、w是s2的子串

3、s3不是w的子串

4、w的长度应尽可能大

所谓子串是指:在字符串中连续的一段

Input

输入有三行,第一行为一个字符串s1第二行为一个字符串s2,

第三行为一个字符串s3。输入仅含小写字母,字符中间不含空格。

Output

输出仅有一行,为w的最大可能长度,如w不存在,则输出0。

Sample Input

abcdef

abcf

bc

Sample Output

2

【样例解释】

s1和s2的公共子串有abc,ab,bc,a,b,c,f,其中abc,bc包含子串bc不合法,所以最长的合法子串为ab。

HINT

1<=s1、s2的长度<=50000,1<=s3的长度<=10000

Sol

首先我们考虑没有限制3该怎么做,那当然是二分+hash裸题啦,每次只要二分串的长度mid,然后利用hash在\(O(n)\)时间内判断A,B中有没有相等的长度为mid的串,复杂度\(O(nlogn)\)。

然后如果加入限制3,那么代表我们选择的串里面不能包含串C,解决方法是对于AB串都跑一遍kmp(直接用hash暴力也行)找到所有C串出现的位置,打上标记,之后前缀和加一下。因为二分检验的本质是暴力,所以枚举所有定长子串的时候直接利用前缀和判断即可。具体地,对于AB串中出现C的每个起始位置++,前缀和之后,如果要判断l,r之间有没有串c,只要判断s[ed-lenc+1]-s[st-1]等不等于0即可。

时间复杂度仍然是\(O(nlogn)\)。

这里如果用map的话,复杂度多一个log(懒,最后卡过去了

似乎要卡单哈希?

sa+kmp的做法由于代码量比这个大就没写(逃,

sa把两个串拼一起做,然后依然kmp+前缀和,之后用height更新答案,二分找最靠前的C串出现位置,不断更新答案。

Code

#include <bits/stdc++.h>
using namespace std;
char a[100005],b[100005],c[20005];
int ans,la,lb,lc,nex[20005],s1[100005],s2[100005],h1[100005],h2[100005],bs[100005],P=233333333,h3[100005],h4[100005],as[100005];
map<int,int>mmpa,mmpb;
void getnex()
{
nex[0]=-1;int i=0,j=-1;
while(i<lc) if(j==-1||c[i]==c[j]) nex[++i]=++j;else j=nex[j];
}
void kmp(char *g,int *s,int len)
{
for(int i=0,j=0;i<len;)
{
if(j==-1||g[i]==c[j]) i++,j++;else j=nex[j];
if(j==lc) s[i-lc]++,j=nex[j];
}
for(int i=1;i<len;i++) s[i]+=s[i-1];
}
bool chk(int mid)
{
mmpa.clear();mmpb.clear();
for(int i=0;i<=la-mid;i++)
{
int st=i,ed=i+mid-1;
if(mid>=lc&&s1[ed-lc+1]-(!st?0:s1[st-1])>0) continue;
int tmp=h1[ed]-1ll*h1[st-1]*bs[mid]%P;tmp=(tmp+P)%P;
int emp=h3[ed]-1ll*h3[st-1]*as[mid]%P;emp=(emp+P)%P;
mmpa[tmp]=1;mmpb[emp]=1;
}
for(int i=0;i<=lb-mid;i++)
{
int st=i,ed=i+mid-1;
if(mid>=lc&&s2[ed-lc+1]-(!st?0:s2[st-1])>0) continue;
int tmp=h2[ed]-1ll*h2[st-1]*bs[mid]%P;tmp=(tmp+P)%P;
int emp=h4[ed]-1ll*h4[st-1]*as[mid]%P;emp=(emp+P)%P;
if(mmpa[tmp]&&mmpb[emp]) return 1;
}
return 0;
}
int main()
{
scanf("%s%s%s",a,b,c),la=strlen(a),lb=strlen(b),lc=strlen(c);
bs[0]=1;for(int i=1;i<=100000;i++) bs[i]=1ll*bs[i-1]*1926%P;
as[0]=1;for(int i=1;i<=100000;i++) as[i]=1ll*as[i-1]*817%P;
h1[0]=a[0]-'a'+1;for(int i=1;i<la;i++) h1[i]=(1ll*h1[i-1]*bs[1]+a[i]-'a'+1)%P;
h2[0]=b[0]-'a'+1;for(int i=1;i<lb;i++) h2[i]=(1ll*h2[i-1]*bs[1]+b[i]-'a'+1)%P;
h3[0]=a[0]-'a'+1;for(int i=1;i<la;i++) h3[i]=(1ll*h3[i-1]*as[1]+a[i]-'a'+1)%P;
h4[0]=b[0]-'a'+1;for(int i=1;i<lb;i++) h4[i]=(1ll*h4[i-1]*as[1]+b[i]-'a'+1)%P;
getnex();kmp(a,s1,la);kmp(b,s2,lb);
for(int l=1,r=min(la,lb);l<=r;)
{
int mid=(l+r)>>1;
if(chk(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
}

【bzoj3796】Mushroom追妹纸 hash/sa+kmp+二分的更多相关文章

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

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

  2. BZOJ3796 Mushroom追妹纸(二分答案+后缀数组+KMP)

    求出一个串使得这个串是\(s1,s2\)的子串.串中不包含\(s3\). 如果没有这个\(s3\)就可以二分答案,然后height小于二分值分一组.看看每组里是不是出现过\(s1,s2\)的后缀.判断 ...

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

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

  4. BZOJ3796 : Mushroom追妹纸

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

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

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

  6. [BZOJ 3796]Mushroom追妹纸

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

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

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

  8. 【bzoj3796】Mushroom追妹纸

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

  9. BZOJ 3796 Mushroom追妹纸 哈希+二分(+KMP)

    先把两个串能匹配模式串的位置找出来,然后标记为$1$(标记在开头或末尾都行),然后对标记数组求一个前缀和,这样可以快速查到区间内是否有完整的一个模式串. 然后二分子串(答案)的长度,每次把长度为$md ...

随机推荐

  1. python's twenty-sixth day for me 模块

    configparser 模块: 该模块适用于配置文件的格式与windows ini文件类似,可以包含一个或多个节(section),每个节可以有多个参数(键 = 值). 创建文件: # 创建文件 i ...

  2. springboot成神之——springboot+mybatis+mysql搭建项目简明demo

    springboot+mybatis+mysql搭建项目简明demo 项目所需目录结构 pom.xml文件配置 application.properties文件配置 MyApplication.jav ...

  3. 第十三章 Spring消息(待续)

    ···············

  4. Enumeration & Structures & Protocl & Extension

    [Enumeration and Structures] 1.使用toRaw.fromRaw方法可以在原始值之间.注意enum的定义中使用了case.另外要注意switch中的枚举值. 2.struc ...

  5. web优化

    一个小型的网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构.性能的要求都很简单.随着互联网业务的不断丰富,网站相关的技术经过 ...

  6. 使用Apache IO库操作IO与文件

    --------------siwuxie095                         首先到 Apache官网 下载相关的库文件     Apache官网:http://www.apach ...

  7. MySQL - pt-query-digest的下载与使用

    对于脚本文件,是可以执行的,我们不用安装.所以,但是这个脚本文件没有执行的权限,所以,我们首先赋予这个脚本文件的可执行的权限. 再次查看文件的信息后. 已经有了执行的权限了. 运行脚本的时候,可要注意 ...

  8. ROS导航包的介绍

    博客转载自:https://blog.csdn.net/handsome_for_kill/article/details/53130707#t3 ROS导航包的应用 利用ROS Navigation ...

  9. hibernate使用记录

    1.执行SQL语句而非hql语句,getSession().createQuery(sql2) 执行的是hibernate语句; Query query2 = this.onlineMonitorDa ...

  10. Linux 下安装Yaf扩展

    1.在官网下载了yaf扩展包 yaf-3.0.3.tgz 2.开始安装yaf扩展 tar zxvf yaf-3.0.3.tgz cd yaf-3.0.3 phpize ./configure --wi ...