原文链接https://www.cnblogs.com/zhouzhendong/p/9253173.html

题目传送门 - BZOJ3796

题意

  找一个串 $w$ 满足:

  1、$w$ 是 $s_1$ 的子串

  2、$w$ 是 $s_2$ 的子串

  3、$s_3$ 不是 $w$ 的子串

  4、$w$ 的长度应尽可能大

  输出 $w$ 的长度。

  $|s_1|,|s_2|\leq 50000,|s_3|\leq 10000$

题解

  考虑求两个串 $(s_1,s_2)$ 的最长公共子串,我们可以把他们用一个特殊字符隔开,然后跑一下 $SA$ .。

  然后请你自行证明最长的一定是一个 $height[i]$ ,满足 $SA[i],SA[i-1]$ 这两个位置分别在 $s_1$ 和 $s_2$ 中。

  再考虑加上 $s_3$ 的限制。

  我们 $KMP$ 一下,看看从哪些位置开始,$s_3$ 与由 $s_1,s_2$ 构成的母串重合。

  然后预处理出对于母串的每一个位置,下一个重合点最早出现在哪里,记为 $e[i]$ ,于是从当前位置开始的串长不能超过 $e[i]-i+|s_3|-1$ ,最后统计 $height$ 的时候取个 $\min$ 即可。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=200005;
int m,n,l,fail[N],e[N];
int SA[N],tmp[N],rank[N],height[N],tax[N];
char s[N],t[N];
void KMP(){
fail[0]=0,fail[1]=0;
for (int i=2;i<=l;i++){
int f=fail[i-1];
while (f>0&&t[f+1]!=t[i])
f=fail[f];
fail[i]=f+(t[f+1]==t[i]);
}
int k=0;
for (int i=1;i<=n;i++){
while (k>0&&t[k+1]!=s[i])
k=fail[k];
k+=(t[k+1]==s[i]);
if (k==l)
k=fail[k],e[i-l+1]=i-l+1;
}
}
void Sort(int n,int m){
for (int i=0;i<=m;i++)
tax[i]=0;
for (int i=1;i<=n;i++)
tax[rank[i]]++;
for (int i=1;i<=m;i++)
tax[i]+=tax[i-1];
for (int i=n;i>=1;i--)
SA[tax[rank[tmp[i]]]--]=tmp[i];
}
bool cmp(int rk[],int x,int y,int w){
return rk[x]==rk[y]&&rk[x+w]==rk[y+w];
}
void Suffix_Array(char s[],int n){
memset(SA,0,sizeof SA);
memset(tmp,0,sizeof tmp);
memset(rank,0,sizeof rank);
memset(height,0,sizeof height);
int m=200;
for (int i=1;i<=n;i++)
rank[i]=s[i],tmp[i]=i;
Sort(n,m);
for (int w=1,p=0;p<n;w<<=1,m=p){
p=0;
for (int i=n-w+1;i<=n;i++)
tmp[++p]=i;
for (int i=1;i<=n;i++)
if (SA[i]>w)
tmp[++p]=SA[i]-w;
Sort(n,m);
swap(tmp,rank);
rank[SA[1]]=p=1;
for (int i=2;i<=n;i++)
rank[SA[i]]=cmp(tmp,SA[i],SA[i-1],w)?p:++p;
}
for (int i=1,j,k=0;i<=n;height[rank[i++]]=k)
for (k=max(k-1,0),j=SA[rank[i]-1];s[i+k]==s[j+k];k++);
height[1]=0;
}
bool Type(int x){
return x>m;
}
int main(){
scanf("%s",s+1);
m=strlen(s+1)+1;
s[m]='*';
scanf("%s",s+m+1);
n=strlen(s+1);
scanf("%s",t+1);
l=strlen(t+1);
for (int i=1;i<=n;i++)
e[i]=n+1;
KMP();
for (int i=n-1;i>=1;i--)
e[i]=min(e[i],e[i+1]);
Suffix_Array(s,n);
int ans=0;
for (int i=2;i<=n;i++)
if (Type(SA[i])^Type(SA[i-1]))
ans=max(ans,min(height[i],e[SA[i]]-SA[i]+l-1));
printf("%d",ans);
return 0;
}

  

BZOJ3796 Mushroom追妹纸 字符串 SA KMP的更多相关文章

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

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

  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安装提示No module named setuptools,wget提示ERROR 403: SSL is required

    在下载安装一个python工具时提示报错No module named setuptools [root@kermit supervisor-3.3.0]$ sudo python setup.py ...

  2. [C]va_list可变长参数的使用

    一.概述 运用标准C的头文件stdarg.h提供的宏可以实现函数的自定义传参个数: 二.语法 1.va_list是一个可变长参数类型,在使用可变长参数的函数中可以定义1个或多个va_list类型参数, ...

  3. [PHP]php缓冲 output_buffering的使用详解

    bufferbuffer是一个内存地址空间,Linux系统默认大小一般为4096(4kb),即一个内存页.主要用于存储速度不同步的设备或者优先级不同的设备之间传办理数据的区域.通过buffer,可以使 ...

  4. 5)协程二(yeild from)

     一:yield from说明 python从3.3版本开始使用yield from 替代yield  yield from 结构会在内部自动捕获 StopIteration 异常. 这种处理方式与 ...

  5. Python-Django-Ajax进阶

    ajax上传文件: <h2>基于ajax上传文件</h2><p>名字 <input type="text" id="filena ...

  6. C#实现向excel中插入行列,以及设置单元格合并居中效果

    插入空行: Microsoft.Office.Interop.Excel.Workbook xlsWorkbook; Microsoft.Office.Interop.Excel.Worksheet ...

  7. Oracle 闪回

    Oracle 闪回特性(FLASHBACK DATABASE) 本文来源于:gerainly 的<Oracle 闪回特性(FLASHBACK DATABASE) > -========== ...

  8. Confluence 6 缓存性能优化

    Confluence 的运行状态与缓存状态有这密切的关系.针对 Confluence 的管理员来说,尤其是大型站点的 Confluence 管理员,设置好缓存尤其显得关键. 希望修改缓存的大小: 进入 ...

  9. vue阿里上传图片报400错误

    首先我用vue上传阿里图片用的是分片上传,分片上传由于一片是以100kb为起始的,所以当图片大小小于100kb的时候不分片,可以正常上传,当大于100kb的时候,会报400错误如下 One or mo ...

  10. Linux基础实操五

    实操一:nginx服务 二进制安装nginx包1) 1)#yum clean all 2)#yum install epel-release -y 3)#yum install nginx -y 1) ...