四合一的题。

简单粗暴的方法:

子串匹配——SAM

子序列匹配——序列自动机

关于序列自动机:序列自动机—— [FJOI2016]所有公共子序列问题

(其实这个玩意没有什么,n+1个点,每个点的字符集的每条出边连向其后的第一个字符,这样保证尽可能用靠前的,后面的能凑出的子序列就能更多,1号点是rt)

类似于SAM,序列自动机的路径条数就是子序列个数。

这样的话,对AB两个串各建造一个SAM和序列自动机

四问就分别在两个机子上bfs跑

如果A有的出边,而B没有,那么返回深度作为答案。

否则A,B都有,入队。

正确性:bfs按深度,会把深度为d的所有公共的子串/子序列搜完后再搜下一个。第一个合法的就是最短的。

复杂度:记忆化一下,因为到了同样一个数对(Ax,By)时候,后面的路径都是固定的了。之前没有找到过,后面也不会找到。直接continue

这样,复杂度就是状态数O(n^2)

就是考察对自动机"路径与子串一一对应"的理解。

#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=;
char a[N],b[N];
int l1,l2;
struct SAM{
int nd,cnt,fa[*N],ch[*N][];
int len[*N];
SAM(){
nd=cnt=;
}
void ins(int c,int pos){
//cout<<c<<" "<<pos<<" "<<cnt<<endl;
int p=nd;nd=++cnt;
len[nd]=pos;
for(;p&&ch[p][c]==;p=fa[p]) ch[p][c]=nd;
if(p==) {fa[nd]=;return;}
int q=ch[p][c];
if(len[q]==len[p]+){fa[nd]=q;return;}
len[++cnt]=len[p]+;
for(reg i=;i<=;++i) ch[cnt][i]=ch[q][i];
fa[cnt]=fa[q];fa[q]=cnt;fa[nd]=cnt;
for(;p&&ch[p][c]==q;p=fa[p]) ch[p][c]=cnt;
}
}SA,SB;
struct XU{
int cnt,ch[N][];
int las[];
void build(char *s,int len){
for(reg i=len;i>=;--i){
for(reg j=;j<=;++j){
if(las[j]) {
ch[i+][j]=las[j];
//cout<<" to "<<i+1<<" "<<j<<" "<<las[j]<<endl;
}
}
if(i)las[s[i]-'a']=i+;
}
}
}XA,XB;
struct po{
int x,y,d;
po(){}
po(int xx,int yy,int dd){
x=xx,y=yy,d=dd;
}
};
queue<po>q;
int vis[*N][*N];
int bfs1(){
while(!q.empty()) q.pop();
q.push(po(,,));
vis[][]=;
while(!q.empty()){
po now=q.front();q.pop();
for(reg i=;i<=;++i){
if(vis[SA.ch[now.x][i]][SB.ch[now.y][i]]==) continue;
vis[SA.ch[now.x][i]][SB.ch[now.y][i]]=;
if(SA.ch[now.x][i]&&!SB.ch[now.y][i]) return now.d+;
if(SA.ch[now.x][i])
{
q.push(po(SA.ch[now.x][i],SB.ch[now.y][i],now.d+));
}
}
}
return -;
}
int bfs2(){
while(!q.empty()) q.pop();
q.push(po(,,));
vis[][]=;
while(!q.empty()){
po now=q.front();q.pop();
for(reg i=;i<=;++i){
if(vis[SA.ch[now.x][i]][XB.ch[now.y][i]]==) continue;
vis[SA.ch[now.x][i]][XB.ch[now.y][i]]=;
if(SA.ch[now.x][i]&&!XB.ch[now.y][i]) return now.d+;
if(SA.ch[now.x][i])
{
q.push(po(SA.ch[now.x][i],XB.ch[now.y][i],now.d+));
}
}
}
return -;
}
int bfs3(){
while(!q.empty()) q.pop();
q.push(po(,,));
vis[][]=;
while(!q.empty()){
po now=q.front();q.pop();
for(reg i=;i<=;++i){
if(vis[XA.ch[now.x][i]][SB.ch[now.y][i]]==) continue;
vis[XA.ch[now.x][i]][SB.ch[now.y][i]]=;
if(XA.ch[now.x][i]&&!SB.ch[now.y][i]) return now.d+;
if(XA.ch[now.x][i])
{
q.push(po(XA.ch[now.x][i],SB.ch[now.y][i],now.d+));
}
}
}
return -;
}
int bfs4(){
while(!q.empty()) q.pop();
q.push(po(,,));
vis[][]=;
while(!q.empty()){
po now=q.front();q.pop();
//cout<<now.x<<" || "<<now.y<<" dd "<<now.d<<endl;
for(reg i=;i<=;++i){
if(vis[XA.ch[now.x][i]][XB.ch[now.y][i]]==) continue;
vis[XA.ch[now.x][i]][XB.ch[now.y][i]]=;
if(XA.ch[now.x][i]&&!XB.ch[now.y][i]) return now.d+;
if(XA.ch[now.x][i])
{
//cout<<" goto "<<XA.ch[now.x][i]<<" "<<
q.push(po(XA.ch[now.x][i],XB.ch[now.y][i],now.d+));
}
}
}
return -;
}
int main(){
scanf("%s",a+);
scanf("%s",b+);
l1=strlen(a+);l2=strlen(b+); for(reg i=;i<=l1;++i) SA.ins(a[i]-'a',i);
for(reg i=;i<=l2;++i) SB.ins(b[i]-'a',i);
//cout<<SA.cnt<<" "<<SB.cnt<<endl;
XA.build(a,l1);XB.build(b,l2);
printf("%d\n%d\n%d\n%d",bfs1(),bfs2(),bfs3(),bfs4());
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2018/12/12 9:10:40
*/

考虑到,我们要最小化一个串的长度,使得这个串在B的机子上跑完回到NULL节点。

所以,也可以DP做。f[i][j]表示,考虑A中前i个位置,匹配到B的机子上的j位置,最小长度。直接在所有机子位置后尝试匹配i+1位,取min即可完成转移。

答案就是f[lenA][NULL]

[HEOI2015]最短不公共子串的更多相关文章

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

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

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

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

  3. 洛谷 P4112 [HEOI2015]最短不公共子串 解题报告

    P4112 [HEOI2015]最短不公共子串 题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的"子串"指的是它的连续的一段,例如bcd是 ...

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

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

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

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

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

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

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

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

  8. BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心

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

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

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

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

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

随机推荐

  1. z-blog博客组插件openSug.js百度搜索下拉框提示代码

      z-blog安装openSug插件即可获得带有“搜索框提示”功能的搜索框,让z-blog搜索更便捷! https://www.opensug.org/.../opensug_z-blog_v1.0 ...

  2. Java学习笔记七:Java的流程控制语句之switch

    Java条件语句之 switch 当需要对选项进行等值判断时,使用 switch 语句更加简洁明了.例如:根据考试分数,给予前四名不同的奖品.第一名,奖励笔记本一台:第二名,奖励 IPAD 2 一个: ...

  3. R语言绘图:直方图

    使用ggplot2包绘制直方图 ######*****绘制直方图代码*****####### data1 <- data0[(data0[, 2] <= 500) & (data0 ...

  4. app:showAsAction 和android:showAsAction

    app:showAsAction 它有三个可选项1.always:总是显示在界面上2.never:不显示在界面上,只让出现在右边的三个点中3.ifRoom:如果有位置才显示,不然就出现在右边的三个点中 ...

  5. 【转】odoo11新功能及绿色版汇总

    昆山-Jeffery 11:34:00 ,odoo11 新功能: 评论:看到截图,感觉美工上又有所提高 官方的发布说明:https://www.odoo.com/nl_NL/page/odoo-11- ...

  6. 3155: Preprefix sum

    3155: Preprefix sum https://www.lydsy.com/JudgeOnline/problem.php?id=3155 分析: 区间修改,区间查询,线段树就好了. 然后,这 ...

  7. 单服务器最大tcp连接数及调优汇总

    启动线程数: 启动线程数=[任务执行时间/(任务执行时间-IO等待时间)]*CPU内核数 最佳启动线程数和CPU内核数量成正比,和IO阻塞时间成反比.如果任务都是CPU计算型任务,那么线程数最多不超过 ...

  8. 解析HTML利器AngleSharp介绍

    解析HTML利器AngleSharp介绍 AngleSharp是基于.NET(C#)开发的专门为解析xHTML源码的DLL组件. 项目地址:https://github.com/FlorianRapp ...

  9. Delphi实例之绘制正弦函数图像

    Delphi实例之绘制正弦函数图像 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphic ...

  10. Django笔记 —— 表单(form)

    最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过.Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧- 本篇笔记(其 ...