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] 表示的 ...
随机推荐
- 在Mac OS X中下载Android源代码的一些经验
首先说明.随着最近(2014年6月開始)GFW的升级.这个站点:http://www.android.com/ 已经不能正常訪问了,以下的这些操作均是在我连接VPN的时候进行的. 首先,须要做一些准备 ...
- 使用Excel2007去反复功能时要注意的一个问题
作者:iamlaosong Excel2007有个去反复功能(菜单:数据----删除反复项).非常实用,过去须要用VBA编程实现的功能,如今点击一下图标即可了.去反复通常是指定某列或者某几列.依据这指 ...
- 搭建私有Nuget仓库
使用Nexus搭建私有Nuget仓库 https://www.cnblogs.com/Erik_Xu/p/9211471.html 前言 Nuget是ASP .NET Gallery的一员,是免费.开 ...
- 查询SQL2008字段和注释
SELECT 表名 then d.name else '' end, 表说明 then isnull(f.value,'') else '' end, 字段序号 = a.colorder, 字段名 = ...
- python读写数据篇
一.读写数据1.读数据 #使用open打开文件后一定要记得调用文件对象的close()方法.比如可以用try/finally语句来确保最后能关闭文件.file_object = open('thefi ...
- JS基础常识理解
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 【BZOJ4999】This Problem Is Too Simple! 离线+树状数组+LCA
[BZOJ4999]This Problem Is Too Simple! Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2 ...
- JAVA解析XML之SAX方式
JAVA解析XML之SAX方式 SAX解析xml步骤 通过SAXParseFactory的静态newInstance()方法获取SAXParserFactory实例factory 通过SAXParse ...
- 子串的索引 str.index(sub) sub必须存在
ii.lstrip(' ')[0:2]=='//' ii.lstrip(' ').index('//')==0
- exception_action
for i in range(3, -2, -1): try: print(4 / i) except Exception as e: print(Exception) print(e)