bzoj3796
好像已经很久没有做后缀数组的题目,导致这种题一开始没想出来
看到公共子串肯定想到后缀数组吧,但我都忘了最长公共子串怎么求了
重要的性质:最长公共子串=max(h[i])名次相邻的两个后缀要分别属于s1,s2串 具体怎么证很简单
这道题多了一个条件,就是公用子串不能包含某个串——很明显想到KMP
我们可以预处理与s3匹配的起始位置,然后处理每个点右边最近的起始位置
然后在穷举h[i]的时候判断一下即可
var h,f,x,y,sum,sa,rank:array[..] of longint;
v:array[..] of boolean;
j,t,st,en,ans,i,p,l,n,m:longint;
s,ss:ansistring;
fl:boolean; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; procedure suffix;
var i,p,j,m:longint;
begin
m:=;
for i:= to n do
begin
y[i]:=ord(s[i]);
inc(sum[y[i]]);
end;
for i:= to m do
inc(sum[i],sum[i-]);
for i:=n downto do
begin
sa[sum[y[i]]]:=i;
dec(sum[y[i]]);
end;
p:=;
rank[sa[]]:=;
for i:= to n do
begin
if y[sa[i]]<>y[sa[i-]] then inc(p);
rank[sa[i]]:=p;
end;
m:=p;
j:=;
while m<n do
begin
y:=rank;
fillchar(sum,sizeof(sum),);
p:=;
for i:=n-j+ to n do
begin
inc(p);
x[p]:=i;
end;
for i:= to n do
if sa[i]>j then
begin
inc(p);
x[p]:=sa[i]-j;
end;
for i:= to n do
begin
rank[i]:=y[x[i]];
inc(sum[rank[i]]);
end;
for i:= to m do
inc(sum[i],sum[i-]);
for i:=n downto do
begin
sa[sum[rank[i]]]:=x[i];
dec(sum[rank[i]]);
end;
p:=;
rank[sa[]]:=;
for i:= to n do
begin
if (y[sa[i]]<>y[sa[i-]]) or (y[sa[i-]+j]<>y[sa[i]+j]) then inc(p);
rank[sa[i]]:=p;
end;
m:=p;
j:=j shl ;
end;
p:=;
h[]:=;
for i:= to n do
begin
if rank[i]= then continue;
j:=sa[rank[i]-];
while s[i+p]=s[j+p] do inc(p);
h[rank[i]]:=p;
if p> then dec(p);
end;
end; begin
readln(s);
readln(ss);
p:=length(s)+;
s:=s+chr()+ss+chr();
n:=length(s); readln(ss);
l:=length(ss);
ss:=ss+' ';
for i:= to l do
begin
j:=f[i-];
while (j>) and (ss[j+]<>ss[i]) do j:=f[j];
if ss[j+]=ss[i] then f[i]:=j+ else f[i]:=;
end; j:=;
for i:= to p- do
begin
while (j>) and (ss[j+]<>s[i]) do j:=f[j];
if ss[j+]=s[i] then
begin
inc(j);
if j=l then v[i-l+]:=true;
end
else j:=;
end; t:=;
for i:=p- downto do
begin
if v[i] then t:=i;
f[i]:=t; //右边最近的匹配起始节点
end;
suffix;
ans:=;
for i:= to n do
begin
fl:=false;
if (sa[i]<p) and (sa[i-]>p) and (sa[i-]<n) then
begin
st:=sa[i];
en:=f[st];
fl:=true;
end;
if (sa[i]>p) and (sa[i]<n) and (sa[i-]<p) then
begin
st:=sa[i-];
en:=f[st];
fl:=true;
end;
if fl then
begin
if h[i]>=en-st+l then //判断是否包含了匹配串
ans:=max(ans,en-st+l-)
else ans:=max(ans,h[i]);
end;
end;
writeln(ans);
end.
bzoj3796的更多相关文章
- BZOJ3796 Mushroom追妹纸 字符串 SA KMP
原文链接https://www.cnblogs.com/zhouzhendong/p/9253173.html 题目传送门 - BZOJ3796 题意 找一个串 $w$ 满足: 1.$w$ 是 $s_ ...
- 【bzoj3796】Mushroom追妹纸
Portal -->bzoj3796 Description 给出字符串s1.s2.s3,找出一个字符串w,满足: 1.w是s1的子串: 2.w是s2的子串: 3.s3不是w的子串. 求w的 ...
- 【BZOJ3796】Mushroom追妹纸 二分+hash
[BZOJ3796]Mushroom追妹纸 Description Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决 ...
- BZOJ3796 : Mushroom追妹纸
将S1与S2用#号拼接在一起形成S串 将S3与S串跑KMP求出S3在S串中每次出现的位置l[i] 对于S串每个后缀i,求出f[i]表示该串不包含S3串的最长前缀 然后求出S串的后缀数组 先从小到大扫描 ...
- bzoj3796(后缀数组)(SA四连)
bzoj3796Mushroom追妹纸 题目描述 Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他从 ...
- 【bzoj3796】Mushroom追妹纸 Kmp+二分+Hash
题目描述 给出字符串s1.s2.s3,找出一个字符串w,满足: 1.w是s1的子串: 2.w是s2的子串: 3.s3不是w的子串. 4.w的长度应尽可能大 求w的最大长度. 输入 输入有三行,第一行为 ...
- 【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 ...
随机推荐
- C# 清除当前窗体中TextBox控件中的内容
//当有多个窗体时,对顶层的窗口进行操作,例如:我们开发具有录入功能的界面的时候,为了防止提交后的二次(重复)录入,希望点击提交按钮并提示成功后,界面的所有文本框内容能够自动清空.NET Framew ...
- 学习S5
rztyfx的专栏 目录视图 摘要视图 订阅 [专家问答]阿里陈康贤:探讨大型网站之架构 走进VR开发世界——我们离开发一款VR大作还有多远? C ...
- 解决在管理wordpress时权限不足的问题
我的wordpress网站的运行环境是自己手动搭建的lamp环境,在管理wordpress时经常遇到因没有足够的权限而无法执行某些操作.在linux上的权限不足的问题无外乎有两个原因,一个是wordp ...
- Android开发系列之ListView
上篇博客解决了Android客户端通过WebService与服务器端程序进行交互的问题,这篇博客重点关注两个问题,一个是Android应用程序如何与本机文件型数据库SQLite进行交互,另一问题则是如 ...
- Centos 6.4 /usr/src/kernels 目录为空解决方法
/usr/src/kernels 目录下是Linux的内核源码,如果其为空,则需要安装安装 kernel-headers 和 kernel-devel包
- Dreamweaver 添加 cakephp ctp后缀名
Dreamweaver 默认是不支持ctp文件高亮的,即使用Dreamweaver打开ctp文件,也只能像记事本一样编辑 但是我们可以通过修改两个文件,来添加Dreamweaver对ctp文件的扩展支 ...
- linux编译相关知识
(1)用g++编译程序时,-l 与-L各是什么意思 http://bbs.chinaunix.net/thread-107364-1-1.html 感谢作者 -l 表示:编译程序到系统默认路进搜索,如 ...
- 开发设计模式(五)单例模式(Singleton Pattern)
http://blog.sina.com.cn/s/blog_89d90b7c0101805m.html 单例模式:意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提 ...
- ubuntu安装svn manager
环境:系统ubuntu14.04 0. 更新软件库 sudo apt-get update sudo apt-get upgrade -y 1. 安装apache,svn,svn的apache模块 s ...
- [转载]C# 判断字符是否中文还是英文
private static bool IsHanZi(string ch) { byte[] byte_len = System.Text.Encoding.Default.GetBytes(ch) ...