分析

这道题有个\(O(n)\)的后缀自动机做法,感觉很好理解就在这说一下。

先对\(s1\)和\(s2\)求最长公共子串,对于\(s2\)的每一个下标\(i\),求一个\(f[i]\)表示以\(s2[i]\)结尾的最长匹配长度。

KMP求出\(s3\)在\(s2\)上的所有结束位置,然后扫一遍\(s2\)统计答案,很简单。

代码

#include <bits/stdc++.h>
#define rin(i,a,b) for(register int i=(a);i<=(b);++i)
#define irin(i,a,b) for(register int i=(a);i>=(b);--i)
#define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl; const int MAXN=50005;
int len1,len2,len3,las,tot,maxlen[MAXN],nxt[MAXN];
char s1[MAXN],s2[MAXN],s3[MAXN];
bool mat[MAXN];
struct sam{
int fa,to[26];
int len;
}a[MAXN<<1]; void extend(int c){
int p=las,np=++tot;las=np,a[np].len=a[p].len+1;
while(p&&!a[p].to[c]) a[p].to[c]=np,p=a[p].fa;
if(!p){a[np].fa=1;return;}
int q=a[p].to[c];
if(a[p].len+1==a[q].len){a[np].fa=q;return;}
int nq=++tot;a[nq]=a[q],a[nq].len=a[p].len+1,a[np].fa=a[q].fa=nq;
while(p&&a[p].to[c]==q) a[p].to[c]=nq,p=a[p].fa;
} void kmp(){
nxt[1]=0;
for(register int i=2,j=0;i<=len3;++i){
while(j&&s3[i]!=s3[j+1]) j=nxt[j];
if(s3[i]==s3[j+1]) ++j;
nxt[i]=j;
}
for(register int i=1,j=0;i<=len2;++i){
while(j&&s2[i]!=s3[j+1]) j=nxt[j];
if(s2[i]==s3[j+1]) ++j;
if(j==len3){
mat[i]=true;
j=nxt[j];
}
}
} void solve(){
int now=1,cur=0;
rin(i,1,len2){
while(now&&!a[now].to[s2[i]-'a']) now=a[now].fa,cur=a[now].len;
if(!now){now=1,cur=0;continue;}
now=a[now].to[s2[i]-'a'],++cur;
maxlen[i]=cur;
}
} int main(){
scanf("%s",s1+1);
getchar();
scanf("%s",s2+1);
getchar();
scanf("%s",s3+1);
len1=strlen(s1+1);
len2=strlen(s2+1);
len3=strlen(s3+1);
las=tot=1;
rin(i,1,len1) extend(s1[i]-'a');
kmp();
solve();
int ans=0,lim=1e9;
rin(i,1,len2){
if(mat[i]) lim=len3-1;
ans=std::max(ans,std::min(maxlen[i],lim++));
}
printf("%d\n",ans);
return 0;
}

[BZOJ3796]Mushroom追妹纸:后缀自动机+KMP的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ3796 : Mushroom追妹纸

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

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

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3796 长度一般都是 1e5 ,看这个是 5e4 ,一看就是把两个串接起来做. 自己本来想的是 ...

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

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3796 先把三个串拼在一起,KMP 求 s1 , s2 中每个位置和 s3 的匹配情况: 注意 ...

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

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

  9. [BZOJ 3796]Mushroom追妹纸

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

随机推荐

  1. WebService概念解释

    一句话概括什么是WebService   WebService是一种跨编程语言.跨操作系统平台的远程调用技术. 远程调用技术:远程调用是指一台设备上的程序A可以调用另一台设备上的方法B.比如:银联提供 ...

  2. Python:什么是进阶,如何进阶?

    目录 Python:什么是进阶,如何进阶? 1. 什么是进阶? 2. 如何进阶? 3. 除此之外呢? Python:什么是进阶,如何进阶? 1. 什么是进阶? 一门编程语言的基础部分,往往非常简单.如 ...

  3. mybatis中foreach的用法以及特殊的情况的用法

    foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合. foreach元素的属性主要有 item,index,collection,open,separator,close. ...

  4. HRBUST 1849 商品中心

    vjudge 智商掉线... 可以发现一条边能贡献其他点当且仅当两点路径上这个边权值最小,所以如果按照边权从大到小加边,每加一条边就会合并两个联通块,那么一个联通块内的点到另一个联通块的点的权值就都是 ...

  5. java json对象转换

    引入的jar包: commons-beanutils-1.9.2.jar commons-collections-3.2.1.jar commons-lang-2.6.jar commons-logg ...

  6. JS递归及二叉搜索树的移除节点

    1递归含义:在某时某刻某个条件下调用包含自己的函数 2:注意点:⑴递归过程中一定要加限制条件,要不然会陷入死循环: 死循环eg: function f(someP){ f(somP); } f(4); ...

  7. java 返回输入中出现次数最多的字符串

    举例输入: abc abc de de de fghi fghi 应该返回: de 代码: static List<String> func(String str) { String[] ...

  8. Delphi上机步骤

  9. AIX中逻辑卷管理

    1.逻辑卷管理 逻辑卷的大小确定: 逻辑卷大小(MB)=PP的大小(MB)*LV包含的LP的个数 LV占用的物理空间(MB)=PP的大小(MB)*LV包含的LP的个数*LV拷贝的副本数   逻辑卷控制 ...

  10. Codeforces 903 绝对值1e19longdouble算贡献 汉明距离交换两项是否可行

    A /*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_bac ...