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

操作一:对A,B分别建SAM,暴力BFS。

操作二:对B建序列自动机或SAM,A在上面暴力匹配。

操作三:对A,B建序列自动机,暴力匹配。

操作四:对B建序列自动机,在自动机上DP。

上面的我一句也看不懂,对不起我重说一遍。

操作一:对B的所有后缀建Trie,A在上面暴力跑。$O(n^2)$

操作二:枚举A的子串,在B上暴力匹配。$O(n^2)$

操作三:在B的每个点上挂一个原本没有的叶子,将从根到这个叶子的路径形成的串扔到A上暴力跑匹配,若A有这个串则更新答案(因为是新叶子故B肯定没有这个串)。但这样似乎是$O(n^3*26)$的,注意枚举点的顺序,按建立顺序从后往前枚举,对于所有深度>=当前ans的直接跳过,这样就近似为$O(n^2*26)$了。似乎可以卡掉,但感觉并不会有出题人去卡。

操作四:DP,f[i][j]表示A的前i个字符中选j个,在B的最小匹配末尾下标的最大值。每次只要从f[pre[i][c]][j-1]转移,其中pre[i][c]为A的第i个位置前的最接近i的字母c的位置。$O(n^2*26)$

 #include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
using namespace std; const int N=,M=,inf=1e9;
int n,m,nd=,ans,son[M][],fa[M],dep[M],pre[N][],nxt[N][],f[N][N];
char st[M],A[N],B[N],s[N]; void ins(int d){
int x=;
rep(i,d,m){
int c=B[i]-'a'+;
if (!son[x][c]) son[x][c]=++nd,fa[nd]=x,st[nd]=B[i],dep[nd]=dep[x]+;
x=son[x][c];
}
} void walk(int d){
int x=;
rep(i,d,n){
int c=A[i]-'a'+;
if (!son[x][c]) { ans=min(ans,i-d+); return; }
x=son[x][c];
}
} void work(int d){
int p=d;
for (int i=; i<=m && p<=n; i++)
if (B[i]==A[p]) p++;
if (p<=n) ans=min(ans,p-d+);
} void work2(int tot){
int p=;
for (int i=; i<=n && p<=tot; i++)
if (A[i]==s[p]) p++;
if (p>tot) ans=min(ans,tot);
} void solve1(){
ans=inf;
rep(i,,n) walk(i);
printf("%d\n",ans==inf ? - : ans);
} void solve2(){
ans=inf;
rep(i,,n) work(i);
printf("%d\n",ans==inf ? - : ans);
} void solve3(){
ans=inf;
for (int i=nd; i; i--) if (dep[i]<ans){
int tot=;
for (int k=i; k>; k=fa[k]) s[++tot]=st[k];
reverse(s+,s+tot+); tot++;
rep(j,,) if (!son[i][j]) s[tot]=j+'a'-,work2(tot);
}
printf("%d\n",ans==inf ? - : ans);
} void solve4(){
ans=inf;
rep(i,,n){
rep(j,,) pre[i][j]=pre[i-][j];
pre[i][A[i-]-'a'+]=i-;
}
for (int i=n-; ~i; i--){
rep(j,,) nxt[i][j]=nxt[i+][j];
nxt[i][B[i+]-'a'+]=i+;
}
rep(i,,n){
int t=nxt[][A[i]-'a'+];
if (t) f[i][]=max(f[i][],t); else { puts(""); return; }
}
rep(i,,n) rep(j,,i) rep(k,,) if (pre[i][k]){
int t=nxt[f[pre[i][k]][j-]][A[i]-'a'+];
if (!t) { ans=min(ans,j); break; }
f[i][j]=max(f[i][j],t);
}
printf("%d\n",ans==inf ? - : ans);
} int main(){
freopen("bzoj4032.in","r",stdin);
freopen("bzoj4032.out","w",stdout);
scanf("%s%s",A+,B+); n=strlen(A+); m=strlen(B+);
rep(i,,m) ins(i);
solve1(); solve2(); solve3(); solve4();
return ;
}

[BZOJ4032][HEOI2015]最短不公共子串(Trie+DP)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. bzoj 4032: [HEOI2015]最短不公共子串【dp+SAM】

    第一.二问: 就是最小的最长公共长度+1,设f[i][j]为a匹配到i,b匹配到j,第一问的转移是f[i][j]=(a[i]==b[j]?f[i-1][j-1]+1:0),第二问的转移是f[i][j] ...

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

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

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

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

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

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

随机推荐

  1. Spring Boot中使用MongoDB数据库

    前段时间分享了关于Spring Boot中使用Redis的文章,除了Redis之后,我们在互联网产品中还经常会用到另外一款著名的NoSQL数据库MongoDB. 下面就来简单介绍一下MongoDB,并 ...

  2. 【洛谷 P2865】 [USACO06NOV]路障Roadblocks(最短路)

    题目链接 次短路模板题. 对每个点记录最短路和严格次短路,然后就是维护次值的方法了. 和这题一样. #include <cstdio> #include <queue> #in ...

  3. 【洛谷 P1502】 窗口的星星(扫描线)

    题目链接 把每个星星作为左下角,做出长为\(w-0.5\),宽为\(h-0.5\)的矩形. \(-0.5\)是因为边框上的不算. 离散化\(y\)坐标. 记录\(2n\)个\(4\)元组\((x,y1 ...

  4. koa源码阅读[0]

    koa源码阅读[0] Node.js也是写了两三年的时间了,刚开始学习Node的时候,hello world就是创建一个HttpServer,后来在工作中也是经历过Express.Koa1.x.Koa ...

  5. 使用Burpsuite爆破弱口令教工号

    使用Burpsuite爆破弱口令教工号 发表于 2015-11-18   |   分类于 Burpsuite  |   1条评论  |   26次阅读 准备 所谓工欲善其事,必先利其器,首先当然是要下 ...

  6. openjudge-NOI 2.6-2728 摘花生

    题目链接:http://noi.openjudge.cn/ch0206/2728/ 题解: 某一个点只能从其左边或者上边走过来 f[i][j]存储(i,j)这个点上的结果,即f[i][j]=max(f ...

  7. Python递归 — — 二分查找、斐波那契数列、三级菜单

    一.二分查找 二分查找也称之为折半查找,二分查找要求线性表(存储结构)必须采用顺序存储结构,而且表中元素顺序排列. 二分查找: 1.首先,将表中间位置的元素与被查找元素比较,如果两者相等,查找结束,否 ...

  8. 调用HTMLTestRunner生产的报告内容为空解决办法

    开始代码如下,生成报告内容为空: #coding=utf-8 import unittest,time,reimport requestsimport jsonimport HTMLTestRunne ...

  9. docker简单介绍(资料收集总结)

    [前言] 首先,感谢我的leader总是会问我很多技术的基本资料,让我这个本来对于各种技术只知道操作命令不关注理论知识的人,开始重视理论资料. 关于docker的操作步骤等等,都是之前学习的,现在补上 ...

  10. [ python ] 线程的操作

    目录 (见右侧目录栏导航) - 1. 前言    - 1.1 进程    - 1.2 有了进程为什么要有线程    - 1.3 线程的出现    - 1.4 进程和线程的关系    - 1.5 线程的 ...