bzoj 4032 [ HEOI 2015 ] 最短不公共子串 —— 后缀自动机+序列自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032
序列自动机其实就是每个位置记录一下某字母后面第一个出现位置,为了子序列能尽量长。
对字符串B建一个后缀自动机,一个序列自动机,然后让A在上面找即可;
1.枚举A每个位置开始的子串,在SAM上走,失配就找到了;
2.枚举A子串,用B的序列自动机找失配处;
3.设 f[i][j] 表示A串前 i 个字符形成的子序列对应SAM上节点 j 时的最短子序列长度,可以转移;
4.f[i][j] 表示A串前 i 个字符的子序列对应B串第 j 个位置时的最短子序列长度,用序列自动机转移;
所以注意 f[i][j] 的第二维要开 4000!否则不是 MLE 而是 WA 。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const xn=,inf=0x3f3f3f3f;
int fa[xn<<],l[xn<<],go[xn<<][],lst=,cnt=,f[xn][xn<<],g[xn][],nxt[];//<<1!!
char s1[xn],s2[xn];
void add(int w)
{
int p=lst,np=++cnt; lst=np; l[np]=l[p]+;
for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
if(!p)fa[np]=;
else
{
int q=go[p][w];
if(l[q]==l[p]+)fa[np]=q;
else
{
int nq=++cnt; l[nq]=l[p]+;
memcpy(go[nq],go[q],sizeof go[q]);
fa[nq]=fa[q]; fa[q]=fa[np]=nq;
for(;go[p][w]==q;p=fa[p])go[p][w]=nq;
}
}
}
int main()
{
scanf("%s",s1+); int l1=strlen(s1+);
scanf("%s",s2+); int l2=strlen(s2+);
for(int i=;i<=l1;i++)s1[i]-='a';
for(int i=;i<=l2;i++)s2[i]-='a';
for(int i=;i<=l2;i++)add(s2[i]);
for(int i=;i<;i++)nxt[i]=l2+;
for(int i=l2;i>=;i--)
{
for(int j=;j<;j++)g[i][j]=nxt[j];
nxt[s2[i]]=i;
} int ans=inf;
for(int i=;i<=l1;i++)
{
int p=,j;
for(j=i;j<=l1;j++)
{
if(!go[p][s1[j]])break;
p=go[p][s1[j]];
}
if(j<=l1)ans=min(ans,j-i+);
}
if(ans==inf)ans=-; printf("%d\n",ans); ans=inf;
for(int i=;i<=l1;i++)
{
if(g[][s1[i]]>l2){ans=min(ans,); continue;}
int p=g[][s1[i]],j;
for(j=i+;j<=l1;j++)
{
if(g[p][s1[j]]==l2+)break;
p=g[p][s1[j]];
}
if(j<=l1)ans=min(ans,j-i+);
}
if(ans==inf)ans=-; printf("%d\n",ans); memset(f,0x3f,sizeof f); f[][]=; ans=inf;
for(int i=;i<l1;i++)
for(int j=,p;j<=cnt;j++)
{
if(f[i][j]==inf)continue;
f[i+][j]=min(f[i+][j],f[i][j]);
if((p=go[j][s1[i+]]))f[i+][p]=min(f[i+][p],f[i][j]+);//,printf("%d %d p=%d\n",j,s1[i+1],p);
else ans=min(ans,f[i][j]+);
}
if(ans==inf)ans=-; printf("%d\n",ans); memset(f,0x3f,sizeof f); f[][]=; ans=inf;
for(int i=;i<l1;i++)
for(int j=,p;j<=l2;j++)
{
if(f[i][j]==inf)continue;
f[i+][j]=min(f[i+][j],f[i][j]);
if((p=g[j][s1[i+]])<l2+)f[i+][p]=min(f[i+][p],f[i][j]+);
else ans=min(ans,f[i][j]+);
}
if(ans==inf)ans=-; printf("%d\n",ans);
return ;
}
bzoj 4032 [ HEOI 2015 ] 最短不公共子串 —— 后缀自动机+序列自动机的更多相关文章
- 解题:HEOI 2015 最短不公共子串
题面 制杖四合一,HEOI以前居然出这种**题,看来HE还是联考比较好= = 首先对第二个串建SAM 第一个简单,以每个位置为起点在SAM上走,失配时更新答案 第二个先在第二个串上预处理$firs[i ...
- bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)
bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp) bzoj Luogu 题解时间 给两个小写字母串 $ A $ , $ B $ ,请你计算: ...
- BZOJ 4032: [HEOI2015]最短不公共子串 后缀自动机 暴力
4032: [HEOI2015]最短不公共子串 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4032 Description 在虐各种最 ...
- bzoj 4032 [HEOI2015]最短不公共子串——后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032 不是 b 的子串的话就对 b 建后缀自动机,在 a 上枚举从每个位置开始的子串或者找子 ...
- BZOJ 4032: [HEOI2015]最短不公共子串(后缀自动机+记忆化搜索)
传送门 解题思路 首先需要预处理两个串\(nxt(i)(j)\)表示i位置之后最近的\(j\). 第一问直接对\(b\)建后缀自动机,枚举\(a\)的起点暴力匹配. 第二问枚举\(a\)的起点,\(b ...
- BZOJ 4032: [HEOI2015]最短不公共子串
4032: [HEOI2015]最短不公共子串 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 446 Solved: 224[Submit][Sta ...
- 【BZOJ】4032: [HEOI2015]最短不公共子串(LibreOJ #2123)
[题意]给两个小写字母串A,B,请你计算: (1) A的一个最短的子串,它不是B的子串 (2) A的一个最短的子串,它不是B的子序列 (3) A的一个最短的子序列,它不是B的子串 (4) A的一个最短 ...
- 【BZOJ4032】[HEOI2015]最短不公共子串(后缀自动机,序列自动机)
[BZOJ4032][HEOI2015]最短不公共子串(后缀自动机,序列自动机) 题面 BZOJ 洛谷 题解 数据范围很小,直接暴力构建后缀自动机和序列自动机,然后直接在两个自动机上进行\(bfs\) ...
- bzoj4032: [HEOI2015]最短不公共子串(SAM+DP)
4032: [HEOI2015]最短不公共子串 题目:传送门 题解: 陈年老题良心%你赛膜爆嘎爷 当初做题...一眼SAM...结果只会两种直接DP的情况... 情况1: 直接设f[i][j] 表示的 ...
随机推荐
- springboot输出日志到指定目录,简单粗暴,springboot输出mybatis日志
springboot官方文档地址https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot- ...
- Linux下文件名正常,下载之后在windows打开为乱码
说明:在Linux下编码为utf-8,在windows下位GBK 1. 2. 3. 4. 5. 6. 7. 8.
- ASP.NET MVC路径引用总结
1.关于路径: (1)绝对路径 包含站点路径的路径:<a href=”http://www.baidu.com/about.jpg”>百度</a> 站点改变路径失效: (2)相 ...
- js document.queryCommandState() 各个参数
命令标识符 2D-Position 允许通过拖曳移动绝对定位的对象. AbsolutePosition 设定元素的 position 属性为“absolute”(绝对). BackColor 设置或获 ...
- PowerBuilder -- 数据窗口
获取数据窗口列数 ls_colnum= integer(this.Describe("DataWindow.Column.Count")) 获取数据窗口列名 ls_colName ...
- ubuntu apt 主要命令及参数
1. apt-cache search package 搜索安装包 2. apt-cache search all 搜索所有安装包 3. apt-cache show package 显示安装包信息 ...
- DataGrid绑定Dictionary问题
问题] 在最近的项目中使用DataGrid的DataGridCheckBoxColumn绑定了后台TagModel类的IsSelected字段,数据源是TagModel类型的Dictionary,运行 ...
- android菜鸟学习笔记12----Android控件(一) 几个常用的简单控件
主要参考<第一行代码> 1.TextView: 功能与传统的桌面应用开发中的Label控件相似,用于显示文本信息 如: <TextView android:layout_width= ...
- Git you are not allowed to push code to protected branches on this project?
error: You are not allowed to push code to protected branches on this project....error: failed to pu ...
- python多进程编程常用到的方法
python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU资源,在python中大部分情况需要使用多进程.python提供了非常好用的多进程包Multiprocessing,只需要定义 ...