题目描述

在虐各种最长公共子串、子序列的题虐的不耐烦了之后,你决定反其道而行之。

一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是。
一个串的“子序列”指的是它的可以不连续的一段,例如bde是abcdef的子串,但bdd不是。
下面,给两个小写字母串A,B,请你计算:
(1) A的一个最短的子串,它不是B的子串
(2) A的一个最短的子串,它不是B的子序列
(3) A的一个最短的子序列,它不是B的子串
(4) A的一个最短的子序列,它不是B的子序列

输入

有两行,每行一个小写字母组成的字符串,分别代表A和B。

输出

输出4行,每行一个整数,表示以上4个问题的答案的长度。如果没有符合要求的答案,输出-1.

样例输入

aabbcc
abcabc

样例输出

2
4
2
4

提示

对于100%的数据,A和B的长度都不超过2000

真正的四合一,一题更比四题强。

本题需要用到序列自动机和后缀自动机,后缀自动机在这里就不赘述了,说一下序列自动机:序列自动机就是对于序列的每一位$i$维护$next[i][j]$表示在第$i$个数之后最早出现$j$数字的位置,构建时只需要倒序枚举序列更新$next$数组即可。设串长为$n$。

子任务1

维护$f[i][j]$表示以$A$的第$i$个字符为结尾的前缀和以$B$的第$j$个字符为结尾的前缀的最长公共后缀,那么对于每个$i$,枚举所有的$j$并取$f[i][j]$的最大值$+1$来更新答案。注意当$f[i][j]$的最大值等于$i$时不能更新答案。时间复杂度为$O(n^2)$

子任务2

对$B$建序列自动机,对于以$A$的第$i$个字符为开头的后缀,我们将它在序列自动机上匹配,当到一个位置失配时,用当前匹配长度$+1$来更新答案。时间复杂度为$O(n^2)$。

子任务3

对$B$建后缀自动机,维护$f[i]$表示$A$的子序列匹配到后缀自动机上的$i$点的最短长度。枚举$A$的每个字符来更新$f$数组:当自动机上当前点$x$能匹配当前枚举字符时$f[to]=min(f[to],f[x]+1)$,否则用$f[x]+1$来更新答案。注意$x$要倒序枚举防止更新到当前层。时间复杂度为$O(n^2)$。

子任务4

与子任务3的做法类似,只需要将后缀自动机换成序列自动机即可。时间复杂度为$O(n^2)$。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
char S[3000];
char T[3000];
namespace subtask1
{
int f[3000][3000];
int solve()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(S[i]==T[j])
{
f[i][j]=f[i-1][j-1]+1;
}
}
}
int ans=1<<30;
for(int i=1;i<=n;i++)
{
int res=0;
for(int j=1;j<=m;j++)
{
res=max(res,f[i][j]);
}
if(res!=i)
{
ans=min(res+1,ans);
}
}
return ans>n?-1:ans;
}
};
namespace subtask2
{
int next[3000][30];
int suf[30];
int solve()
{
for(int i=0;i<26;i++)
{
suf[i]=m+1;
}
for(int i=m;i>=0;i--)
{
for(int j=0;j<26;j++)
{
next[i][j]=suf[j];
}
suf[T[i]-'a']=i;
}
int ans=1<<30;
for(int i=1;i<=n;i++)
{
int now=0;
for(int j=i;j<=n;j++)
{
now=next[now][S[j]-'a'];
if(now>m)
{
ans=min(ans,j-i+1);
break;
}
}
}
return ans>n?-1:ans;
}
};
namespace subtask3
{
int tr[5000][30];
int len[5000];
int pre[5000];
int f[5000];
int cnt=1;
int last=1;
void insert(int x)
{
int p=last;
int np=++cnt;
last=np;
len[np]=len[p]+1;
for(;p&&!tr[p][x];p=pre[p])
{
tr[p][x]=np;
}
if(!p)
{
pre[np]=1;
}
else
{
int q=tr[p][x];
if(len[p]+1==len[q])
{
pre[np]=q;
}
else
{
int nq=++cnt;
pre[nq]=pre[q];
memcpy(tr[nq],tr[q],sizeof(tr[q]));
pre[np]=pre[q]=nq;
len[nq]=len[p]+1;
for(;p&&tr[p][x]==q;p=pre[p])
{
tr[p][x]=nq;
}
}
}
}
int solve()
{
for(int i=1;i<=m;i++)
{
insert(T[i]-'a');
}
memset(f,0x3f,sizeof(f));
f[1]=0;
int ans=1<<30;
for(int i=1;i<=n;i++)
{
for(int j=cnt;j>=1;j--)
{
int now=tr[j][S[i]-'a'];
if(now)
{
f[now]=min(f[now],f[j]+1);
}
else
{
ans=min(ans,f[j]+1);
}
}
}
return ans>n?-1:ans;
}
};
namespace subtask4
{
int next[3000][30];
int f[3000];
int suf[30];
int solve()
{
for(int i=0;i<26;i++)
{
suf[i]=m+1;
}
for(int i=m;i>=0;i--)
{
for(int j=0;j<26;j++)
{
next[i][j]=suf[j];
}
suf[T[i]-'a']=i;
}
memset(f,0x3f,sizeof(f));
f[0]=0;
int ans=1<<30;
for(int i=1;i<=n;i++)
{
for(int j=m;j>=0;j--)
{
int now=next[j][S[i]-'a'];
if(now>m)
{
ans=min(ans,f[j]+1);
}
else
{
f[now]=min(f[now],f[j]+1);
}
}
}
return ans>n?-1:ans;
}
};
int main()
{
scanf("%s%s",S+1,T+1);
n=strlen(S+1);
m=strlen(T+1);
printf("%d\n",subtask1::solve());
printf("%d\n",subtask2::solve());
printf("%d\n",subtask3::solve());
printf("%d\n",subtask4::solve());
}

BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心的更多相关文章

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

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

  2. BZOJ4032 [HEOI2015]最短不公共子串 【后缀自动机 + 序列自动机 + dp】

    题目链接 BZOJ4032 题解 首先膜\(hb\) 空手切神题 一问\(hash\),二问枚举 三问\(trie\)树,四问\(dp\) 南二巨佬神\(hb\) 空手吊打自动机 \(orz orz ...

  3. BZOJ4032: [HEOI2015]最短不公共子串(后缀自动机+序列自动机)

    题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...

  4. [BZOJ4032][HEOI2015]最短不公共子串(Trie+DP)

    在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之——被它们虐. 操作一:对A,B分别建SAM,暴力BFS. 操作二:对B建序列自动机或SAM,A在上面暴力匹配. 操作三:对A,B建 ...

  5. BZOJ4032:[HEOI2015]最短不公共子串(SAM)

    Description 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列” ...

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

    第一问: 对B串建立SAM,暴力枚举A的每个子串,在SAM上走,若失配则可行. 第二问: 设g[i][j]表示B串的第i个字符之后最早出现的字符j的位置,暴力枚举A的每个子串,按照g贪心地走,若失配则 ...

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

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

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

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

  9. luoguP4112 [HEOI2015]最短不公共子串 SAM,序列自动机,广搜BFS

    luoguP4112 [HEOI2015]最短不公共子串 链接 luogu loj 思路 子串可以用后缀自动机,子序列可以用序列自动机. 序列自动机是啥,就是能访问到所有子序列的自动机. 每个点记录下 ...

随机推荐

  1. 《了不起的 nodejs》中 TwitterWeb 案例 bug 解决

    了不起的nodejs算是一本不错的入门书,不过书中个别案例存在bug,按照书中源码无法做出和书中相同效果,原本兴奋的心情掺杂着些许失落. 现在我们看一下第七章HTTP,一个 Twitter Web 客 ...

  2. 使用sklearn做文本特征提取

    提取文本的特征,把文本用特征表示出来,是文本分类的前提,使用sklearn做文本的特征提取,需要导入TfidfVectorizer模块. from sklearn.feature_extraction ...

  3. redis-trib.rb命令详解

    redis-trib.rb是官方提供的Redis Cluster的管理工具,无需额外下载,默认位于源码包的src目录下,但因该工具是用ruby开发的,所以需要准备相关的依赖环境. 准备redis-tr ...

  4. java使用Map做缓存你真的用对了吗?弱引用WeakHashMap了解一下

    目录 关于缓存我们应该考虑什么?-intsmaze WeakHashMap弱引用-intsmaze 线程安全问题-intsmaze Collections-intsmaze ThreadLocal-i ...

  5. 机器学习第一篇——最近邻kNN

    机器学习监督学习中,根据解决问题的连续性和离散型,分为分类问题和回归问题.最邻近算法kNN是一种最为直接和简便的分类方法. kNN本质上,是计算目标到模型的欧式距离,从而判定目标所属的类别. 首先,在 ...

  6. shell脚本--初识CGI

    CGI按照百度百科的定义,如下: CGI 是Web 服务器运行时外部程序的规范,按CGI 编写的程序可以扩展服务器功能.CGI 应用程序能与浏览器进行交互,还可通过数据库API 与数据库服务器等外部数 ...

  7. 【学习总结】Git学习-参考廖雪峰老师教程四-时光机穿梭

    学习总结之Git学习-总 目录: 一.Git简介 二.安装Git 三.创建版本库 四.时光机穿梭 五.远程仓库 六.分支管理 七.标签管理 八.使用GitHub 九.使用码云 十.自定义Git 期末总 ...

  8. vs快捷键 C#

    快速构建构造函数 输入 ctor 然后按 TAB 键 快速构建自动属性 在变量那里,右击鼠标,点“重构”--“封装字段” Visual Studio快捷键 [VS2008/VS2005] ****** ...

  9. Python3练习题 026:求100以内的素数

    p = [i for i in range(2,100)] #建立2-99的列表 for i in range(3,100): #1和2都不用判断,从3开始     for j in range(2, ...

  10. JS 获取链接中的参数

    1.获取链接全部参数,以对象的形式返回 //获取url中参数 function GetRequest() { var url = location.search; //获取url中"?&qu ...