题目: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 ] 最短不公共子串 —— 后缀自动机+序列自动机的更多相关文章

  1. 解题:HEOI 2015 最短不公共子串

    题面 制杖四合一,HEOI以前居然出这种**题,看来HE还是联考比较好= = 首先对第二个串建SAM 第一个简单,以每个位置为起点在SAM上走,失配时更新答案 第二个先在第二个串上预处理$firs[i ...

  2. bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)

    bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp) bzoj Luogu 题解时间 给两个小写字母串 $ A $ , $ B $ ,请你计算: ...

  3. BZOJ 4032: [HEOI2015]最短不公共子串 后缀自动机 暴力

    4032: [HEOI2015]最短不公共子串 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4032 Description 在虐各种最 ...

  4. bzoj 4032 [HEOI2015]最短不公共子串——后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032 不是 b 的子串的话就对 b 建后缀自动机,在 a 上枚举从每个位置开始的子串或者找子 ...

  5. BZOJ 4032: [HEOI2015]最短不公共子串(后缀自动机+记忆化搜索)

    传送门 解题思路 首先需要预处理两个串\(nxt(i)(j)\)表示i位置之后最近的\(j\). 第一问直接对\(b\)建后缀自动机,枚举\(a\)的起点暴力匹配. 第二问枚举\(a\)的起点,\(b ...

  6. BZOJ 4032: [HEOI2015]最短不公共子串

    4032: [HEOI2015]最短不公共子串 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 446  Solved: 224[Submit][Sta ...

  7. 【BZOJ】4032: [HEOI2015]最短不公共子串(LibreOJ #2123)

    [题意]给两个小写字母串A,B,请你计算: (1) A的一个最短的子串,它不是B的子串 (2) A的一个最短的子串,它不是B的子序列 (3) A的一个最短的子序列,它不是B的子串 (4) A的一个最短 ...

  8. 【BZOJ4032】[HEOI2015]最短不公共子串(后缀自动机,序列自动机)

    [BZOJ4032][HEOI2015]最短不公共子串(后缀自动机,序列自动机) 题面 BZOJ 洛谷 题解 数据范围很小,直接暴力构建后缀自动机和序列自动机,然后直接在两个自动机上进行\(bfs\) ...

  9. bzoj4032: [HEOI2015]最短不公共子串(SAM+DP)

    4032: [HEOI2015]最短不公共子串 题目:传送门 题解: 陈年老题良心%你赛膜爆嘎爷 当初做题...一眼SAM...结果只会两种直接DP的情况... 情况1: 直接设f[i][j] 表示的 ...

随机推荐

  1. hibernate 配置文件无自动提示

    在编辑 *.hbm.xml 文件时,myeclipse 带有自动提示功能,但 eclipse 是没有自动提示功能的.需要自己手工加上:           1.打开项目中任意一个 *.hbm.xml ...

  2. SQLServer -- SQL Server Database Error: 内部 SQL Server 错误

    报表在SQLserver2008运行统计正常,但是在SQLserver2000运行报错,SQL直接执行报:内部 SQL Server 错误. 不断的排查,最终得到的结论是:SQLserver2000似 ...

  3. HDU1864 最大报销额 01背包

    非常裸的01背包,水题.注意控制精度 #include <iostream> #include <algorithm> #include <cstdio> #inc ...

  4. PHP进阶知识

    关于PHP程序员技术职业生涯规划:http://rango.swoole.com/ Micro Service Framework For PHP:https://github.com/pinguo/ ...

  5. 【BZOJ3671】[Noi2014]随机数生成器 暴力

    [BZOJ3535][Noi2014]随机数生成器 Description Input 第1行包含5个整数,依次为 x_0,a,b,c,d ,描述小H采用的随机数生成算法所需的随机种子.第2行包含三个 ...

  6. python文件读写方式

    window下换行\r\n linux.unix.mac下都是\n - 以二进制的形式wb写入,同样以二进制的方式读取rb ``` f = open('file name','wb') f.write ...

  7. python中装饰器你真的理解吗?

    def w1(func): print('装饰器1....') def w1_in(): print('w1_in.....') func() return w1_in def w2(func): p ...

  8. 九度OJ 1058:反序输出 (基础题)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:8454 解决:3042 题目描述: 输入任意4个字符(如:abcd), 并按反序输出(如:dcba) 输入: 题目可能包含多组用例,每组用例 ...

  9. BZOJ1815: [Shoi2006]color 有色图

    BZOJ1815: [Shoi2006]color 有色图 Description Input 输入三个整数N,M,P 1< = N <= 53 1< = M < = 1000 ...

  10. mapreduce的一个模版

    import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import j ...