原文链接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. MybatisGenerator生成的mapper 少了识别主键的方法 byPrimaryKey()

    生成的文件缺少红线标注的类似方法 添加 <property name="useInformationSchema" value="true"/>即可 ...

  2. Laravel 5.2服务----用户验证Auth相关问题

    关于laravel的auth()用户认证这一块,面前我也是,有用到,有碰到什么问题我就记录下来. 手动认证用户 <?php namespace App\Http\Controllers; use ...

  3. docker的安装及项目部署

    Making Docker and Deployment Process Step: set up your docker environment build a image of activeMQ ...

  4. jquery中的attr与prop的区别,什么时候用attr,什么时候用prop

    只要有 Boolean() 属性的,简单说就是具有true 和 false 两个属性的属性,如 checked, selected 或者 disabled 使用prop(),(其实这些都是表单类的), ...

  5. Unix的哲学

    先讲两个很老的小故事. 第一个故事. 有一家日本最大的化妆品公司,收到了用户的投诉.用户抱怨买来的肥皂盒是空的.这家公司为了防止再发生这样的事故,很辛苦地发明了一台X光检查器,能够透视每一个出货的肥皂 ...

  6. ORACLE透明加密

    --官网文档:https://www.oracle.com/technetwork/cn/tutorials/tde-096009-zhs.html#t概述Oracle 数据库 10g 第 2 版透明 ...

  7. 对象Object

    功能分类                       1. 创建对象 把各对数自身拥有的可枚举属性复制到第一个对象并返回:obj = Object.assign(o1, o2, o3),o1=obj ...

  8. oracle导出序列的几种办法

    oracle导出序列的几种办法 注:本文来源于<oracle导出序列的几种办法> 方法一: select 'create sequence ' ||sequence_name|| ' mi ...

  9. Confluence 6 配置附件大小

    你可以限制上传到 Confluence 的附件的大小. 配置可以上传到 Confluence 的附件所允许的大小: 进入  > 基本配置(General Configuration). 选择 编 ...

  10. Python实战二

    要求:按照要求完成对文件的增.删.改.查操作. def add(**kwargs): '''新增内容,在指定位置新增''' while True: flag = False with open(&qu ...