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 ...
随机推荐
- 修改placeholder颜色
#contact_info为textarea的ID #contact_info::-webkit-input-placeholder{ color:#999;}#contact_info:-moz-p ...
- 一篇关于学C++的感想(拿来与大家分享)
学计算机的如果你有耐心看下去,我敢保证这绝对是一种收获 期待爱 大师提醒: 计算机专业不是学编程,而是懂得计算机的工作原理,以及和计算机相关的学科技术.一个高手不必懂得编程,coder是最底层的人物, ...
- Linux下的ntp时钟同步问题
前段时间,项目中有个需求,需要将linux和windows的时间进行同步,网上也有很多类似时钟同步的帖子,大致类似:不过本次的linux的机器有点特殊,没有service命令,而且要求在另一台suse ...
- js模拟苹果菜单
模拟苹果菜单的js代码是从网上看到的,用来做导航菜单还是蛮好看的.这里借鉴一下. 效果描述:当鼠标移动离哪个图片最近的时候,这个图片最大,鼠标离的图片越远,则图片越小: 原理:主要用到了三角形的勾股定 ...
- mysql基本知识
最大连接数show variables max_connections; select VARIABLE_VALUE from information_schema.GLOBAL_VARIABLES ...
- java basic
//java 声明常量 //final 数据类型 常量名=值; //as: final float PI=3.14f;/ PI=3.14002F //默认浮点为 double //break:跳出多重 ...
- 建站服务器的最优选择之Windows Or Linux
转载于:http://www.0553114.com/news/detail-702287.html 不管是个人建站,还是中小型企业建站,选择一款合适的主机是站长朋友们共同的心愿.主机是选择Windo ...
- JavaScript 判断用户输入的邮箱及手机格式是否正确
JavaScript判断用户输入的邮箱格式是否正确.判断用户输入的手机号格式是否正确,下面有个不错的示例,感兴趣的朋友可以参考下. 复制代码代码如下: /* * 功能:判断用户输入的邮箱格式是否正确 ...
- AWR报告导出的过程报ORA-06550异常
刚才在笔记本上(win 7)想要导出一套RAC的AWR报告(linux),执行awrgrpt.sql的脚本的过程中报错了,报错的异常代码是:ORA-06550.经过检查,发现是用户的问题,换成sys用 ...
- 洛谷 P1541 乌龟棋
题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...