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 ...
随机推荐
- 09_控制线程_线程睡眠sleep
[线程睡眠] 如果需要让当前正在执行的线程暂停一段时间,并进入阻塞状态,则可以通过调用Thread类的静态方法sleep()方法来实现. sleep()方法有两种重载形式: 1.static void ...
- error C2664 转换错误汇总[转]
vs2005提示 error C2664: “CWnd::MessageBoxW”: 不能将参数 1 从“const char [17]”转换为“LPCTSTR”. 在用vs2005编写mfc程序的时 ...
- mysql数据库之索引和分析索引
分析查询语句是否用到了索引 explain sql语句\G //根据返回的信息,我们可知,该sql语句是否使用索引,从多少记录中取出,可以看到排序的方式. 主要是看 key 实际用到的索引 rows ...
- jsoup 对网页中图片解析
Elements article = new Elements(); Elements Img = new Elements(); article = doc.select("div#con ...
- PHP初学留神(二)
1.===比较运算符 记得上上篇中说过===与==的问题.当时说,===还要类型相同.但到底是怎样呢?因为我们知道比较运算符是可以把两个值类型转换的.举个栗子,如果一个数字和字符串比较,则字符串会转化 ...
- Django环境搭建和项目创建
1.下载安装python 2.打开shell(windows下cmd),安装虚拟环境工具: "pip install virtualenv".(可以通过“python -m pi ...
- 关于 hashCode() 你需要了解的 3 件事
(点击上方公众号,可快速关注) 原文:eclipsesource 译文:ImportNew - 南半球 链接:http://www.importnew.com/16517.html 在 Java 中, ...
- Python Geospatial Development reading note(1)
chapter 1, Summary: In this chapter, we briefly introduced the Python programming language and the m ...
- 创建共享内存函数CreateFileMapping()详解
测试创建和打开文件映射的时候老是得到"句柄无效"的错误, 仔细看了MSDN以后才发觉是函数认识不透, 这里把相关的解释翻译出来 HANDLE CreateFileMapping( ...
- U盘、移动硬盘提示格式化的处理
移动硬盘突然打不开了,一点击就提示要求格式化,这种问题本人亲历,现已解决,千万别格式化,千万别格式化,用系统自带磁盘恢复 CHKDSK命令即可解决此问题 方法/步骤 1.在开始菜单找到“运行”窗口,也 ...