题目链接

BZOJ4032

题解

首先膜\(hb\)

空手切神题

一问\(hash\),二问枚举

三问\(trie\)树,四问\(dp\)

南二巨佬神\(hb\)

空手吊打自动机

\(orz orz orz orz orz orz orz\)

咳。说正解

要处理子串,直接搬上后缀自动机

要处理子序列,直接搬上序列自动机【雾】

何为序列自动机##

序列自动机其实很简单,就是具有识别所有子序列功能的自动机

建机原理及过程及其简单,只需要从后往前扫一遍,对每一个位置建立一个节点,该节点的各个边连向最晚出现的对应的字符对应的节点

只需记录下每个字符最晚出现的节点就可以\(O(n|s|)\)建机了 【\(|s|\)为字符集大小】

代码实现:

struct LAM{
int ch[maxn][26],last[26],cnt;
void ins(int x){
int p = ++cnt;
for (int i = 0; i < 26; i++)
ch[p][i] = last[i];
last[x] = p;
}
void init(){
for (int i = 0; i < 26; i++)
ch[1][i] = last[i];
}
}lam;
......
lam.cnt = 1;
for (int i = len; i; i--) lam.ins(s[i] - 'a');
lam.init();

第一、二问##

只需枚举\(A\)子串的起点,然后看看能在自动机中走多远即可

第三、四问##

与\(A\)的子序列有关,就上\(dp\)

设\(f[i][j]\)表示\(A\)的前\(i\)个字符形成的所有子序列匹配到自动机\(j\)号节点的最短长度

如果\(i\)不选

\[f[i][j] = f[i - 1][j]
\]

如果\(i\)被选,那么枚举是从哪一个节点转移来的

设上一个节点为\(u\)

\[f[i][j] = min\{f[i - 1][u] + 1\}
\]

【注意这里是枚举\(u\)】

答案即为\(f[len][0]\) 【\(0\)表示空,即不匹配】

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 4005,maxm = 100005,INF = 0x3f3f3f3f;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
struct SAM{
int ch[maxn][26],pre[maxn],step[maxn],last,cnt;
void ins(int x){
int p = last,np = ++cnt; step[np] = step[p] + 1; last = np;
while (p && !ch[p][x]) ch[p][x] = np,p = pre[p];
if (!p) pre[np] = 1;
else {
int q = ch[p][x];
if (step[q] == step[p] + 1) pre[np] = q;
else {
int nq = ++cnt; step[nq] = step[p] + 1;
for (int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
pre[nq] = pre[q]; pre[np] = pre[q] = nq;
while (ch[p][x] == q) ch[p][x] = nq,p = pre[p];
}
}
}
}sam;
struct LAM{
int ch[maxn][26],last[26],cnt;
void ins(int x){
int p = ++cnt;
for (int i = 0; i < 26; i++)
ch[p][i] = last[i];
last[x] = p;
}
void init(){
for (int i = 0; i < 26; i++)
ch[1][i] = last[i];
}
}lam;
char A[maxn],B[maxn];
int lena,lenb;
void solve1(){
int ans = INF;
for (int i = 1,j; i <= lena; i++){
int u = 1,cnt = 0;
for (j = i; j <= lena; j++){
++cnt;
if (!sam.ch[u][A[j] - 'a']) break;
u = sam.ch[u][A[j] - 'a'];
}
if (j <= lena) ans = min(ans,cnt);
}
if (ans == INF) puts("-1");
else printf("%d\n",ans);
}
void solve2(){
int ans = INF;
for (int i = 1,j; i <= lena; i++){
int u = 1,cnt = 0;
for (j = i; j <= lena; j++){
++cnt;
if (!lam.ch[u][A[j] - 'a']) break;
u = lam.ch[u][A[j] - 'a'];
}
if (j <= lena) ans = min(ans,cnt);
}
if (ans == INF) puts("-1");
else printf("%d\n",ans);
}
int f[2005][maxn];
void solve3(){
memset(f,INF,sizeof(f));
f[0][1] = 0;
for (int i = 1; i <= lena; i++){
for (int j = 1; j <= sam.cnt; j++) f[i][j] = min(f[i][j],f[i - 1][j]);
for (int j = 1; j <= sam.cnt; j++){
int to = sam.ch[j][A[i] - 'a'];
f[i][to] = min(f[i][to],min(f[i - 1][to],f[i - 1][j] + 1));
}
}
if (f[lena][0] == INF) puts("-1");
else printf("%d\n",f[lena][0]);
}
void solve4(){
memset(f,INF,sizeof(f));
f[0][1] = 0;
for (int i = 1; i <= lena; i++){
for (int j = 1; j <= lam.cnt; j++) f[i][j] = min(f[i][j],f[i - 1][j]);
for (int j = 1; j <= lam.cnt; j++){
int to = lam.ch[j][A[i] - 'a'];
f[i][to] = min(f[i][to],min(f[i - 1][to],f[i - 1][j] + 1));
}
}
if (f[lena][0] == INF) puts("-1");
else printf("%d\n",f[lena][0]);
}
int main(){
scanf("%s",A + 1); lena = strlen(A + 1);
scanf("%s",B + 1); lenb = strlen(B + 1);
sam.last = sam.cnt = 1; lam.cnt = 1;
for (int i = 1; i <= lenb; i++) sam.ins(B[i] - 'a');
for (int i = lenb; i; i--) lam.ins(B[i] - 'a');
lam.init();
solve1();
solve2();
solve3();
solve4();
return 0;
}

BZOJ4032 [HEOI2015]最短不公共子串 【后缀自动机 + 序列自动机 + dp】的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 使用JavaScript动态的绑定、解绑 a 标签的onclick事件,防止重复点击

    页面上的 a 标签如下: <a class="more" style="cursor: pointer;" id="commentMore&qu ...

  2. LINUX安装好后无法访问网络

    LINUX安装好后无法访问网络 在虚拟机安装好新的LINUX系统后,ping www.baidu.com ,发现无法ping通. 键入ifconfig查询配置: eno16777728: flags= ...

  3. Salt-ssh 自动安装salt-minion

    作用:为了不手动去安装一台一台去salt-minion,并进重复的配置 一.环境 系统环境: #cat /etc/redhat-release CentOS Linux release 7.4.170 ...

  4. linux下csv导出文件中文乱码问题

    近日在服务器端通过导出csv文件,将数据从linux服务器端保存到windows桌面端,以便用户可以通过excel打开使用数据. 但是在使用excel打开csv文件时,出现了中文乱码的情况,但是使用记 ...

  5. 千锋教育Vue组件--vue基础的方法

    课程地址: https://ke.qq.com/course/251029#term_id=100295989 <!DOCTYPE html> <html> <head& ...

  6. PyQuery网页解析库

    from pyquery import PyQuery as pq 字符串初始化: doc = pq(html) URL初始化:doc = pq(url = "···") 文件初始 ...

  7. python中全局变量和局部变量

    例1: a = 100 #定义全局变量a def test1(): print(a) #此处a为全局变量 def test2(a):#此处a为局部变量 print(a)#此处a为局部变量 test1( ...

  8. C语言真正的编译过程(4个步骤~~预编译,编译,汇编,连接)

    转载自:https://www.cnblogs.com/wuyouxiaocai/p/5701088.html#commentform 说实话,很多人做了很久的C/C++,也用了很多IDE,但是对于可 ...

  9. 牛客暑假多校第二场J-farm

    一.题意 White Rabbit has a rectangular farmland of n*m. In each of the grid there is a kind of plant. T ...

  10. 7,Flask 中路由系统

    Flask中的路由系统 @app.route("/",methods=["GET","POST"]) 为什么要这么用?其中的工作原理我们知道 ...