BZOJ3796 Mushroom追妹纸 字符串 SA KMP
原文链接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的更多相关文章
- 【bzoj3796】Mushroom追妹纸 hash/sa+kmp+二分
Description Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意--写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他从网上找到了两篇极佳的情书, ...
- BZOJ3796 Mushroom追妹纸(二分答案+后缀数组+KMP)
求出一个串使得这个串是\(s1,s2\)的子串.串中不包含\(s3\). 如果没有这个\(s3\)就可以二分答案,然后height小于二分值分一组.看看每组里是不是出现过\(s1,s2\)的后缀.判断 ...
- [BZOJ3796]Mushroom追妹纸:后缀自动机+KMP
分析 这道题有个\(O(n)\)的后缀自动机做法,感觉很好理解就在这说一下. 先对\(s1\)和\(s2\)求最长公共子串,对于\(s2\)的每一个下标\(i\),求一个\(f[i]\)表示以\(s2 ...
- BZOJ3796 : Mushroom追妹纸
将S1与S2用#号拼接在一起形成S串 将S3与S串跑KMP求出S3在S串中每次出现的位置l[i] 对于S串每个后缀i,求出f[i]表示该串不包含S3串的最长前缀 然后求出S串的后缀数组 先从小到大扫描 ...
- 【BZOJ3796】Mushroom追妹纸 二分+hash
[BZOJ3796]Mushroom追妹纸 Description Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决 ...
- [BZOJ 3796]Mushroom追妹纸
[BZOJ 3796]Mushroom追妹纸 题目 Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他 ...
- 【bzoj3796】Mushroom追妹纸 Kmp+二分+Hash
题目描述 给出字符串s1.s2.s3,找出一个字符串w,满足: 1.w是s1的子串: 2.w是s2的子串: 3.s3不是w的子串. 4.w的长度应尽可能大 求w的最大长度. 输入 输入有三行,第一行为 ...
- 【bzoj3796】Mushroom追妹纸
Portal -->bzoj3796 Description 给出字符串s1.s2.s3,找出一个字符串w,满足: 1.w是s1的子串: 2.w是s2的子串: 3.s3不是w的子串. 求w的 ...
- BZOJ 3796 Mushroom追妹纸 哈希+二分(+KMP)
先把两个串能匹配模式串的位置找出来,然后标记为$1$(标记在开头或末尾都行),然后对标记数组求一个前缀和,这样可以快速查到区间内是否有完整的一个模式串. 然后二分子串(答案)的长度,每次把长度为$md ...
随机推荐
- WINDOWS资源编译器出错信息
ACCELERATORS语句的type域应包含ASCⅡ值或VIRTKEY值. BEGIN expected in table BEGIN关键字应紧跟在ACCELERATOR ...
- Ex 2_5 求解递推式..._第三次作业
- git bash的命令
git bash cd /f 该命令可以把当前目录切换到f盘 git clone git上的项目的url
- VI编辑器、ipython、jupyter及进程知识总结
一.VI编辑器 1.三种模式 一般模式(normal mode 默认) 插入模式(insert mode) 末行模式(last line mode) 2.模式切换 一般模式-------------- ...
- swift 实践- 14 -- UIScrollView
import UIKit class ViewController: UIViewController ,UIScrollViewDelegate{ override func viewDidLoad ...
- Confluence 6 查看索引和提示
查看索引 Confluence 使用被称为 Lucene 的搜索引擎.如果你希望在你的 Confluence站点中查看更多有关索引的细节,你可以下载并且运行 Luke.Luke 是一个开发和诊断工具, ...
- Confluence 6 SQL Server 测试你的数据库连接
在你的数据库设置界面,有一个 测试连接(Test connection)按钮可以检查: Confluence 可以连接你的数据库服务器 数据库字符集和隔离级别是正确的 你的数据库用户有正确的数据库权限 ...
- pod 使用详解
cd 进去到 项目目录 包含 xcodeproj 结尾的目录下 1 pod init 创建一个pod 文件 2 打开生产的pod 文件 然后 配置pod 文件 并保存 3 pod install 安 ...
- 学习Spring Boot:(一)入门
微服务 现在微服务越来越火了,Spring Boot热度蹭蹭直升,自学下. 微服务其实是服务化思路的一种最佳实践方向,遵循SOA(面向服务的架构)的思路,各个企业在服务化治理上面的道路已经走得很远了, ...
- Java编程的分期步骤(一)
日期:2018.8.12 星期一 博客期:005 不知不觉来到第五期了,先简单说一下Java环境!(虽然Java都自学完了才说....)首先,就是在网站上下载一个java包,之后把它下载到全英文的一个 ...