题目链接

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. SAP库存历史库存表更新逻辑 (转)

    根据库存类型的不同,库存信息保存在不同的表中,具体而言见下表 库存类型 当前库存 历史库存 库存金额 历史库存金额 工厂级别库存 MARC MARCH MBEW MBEWH MBEW 库存地点库存 M ...

  2. Maven - 依赖冲突

    依赖冲突有两个规则: 短路优先范例:A -> B -> C -> X-2.0.0A -> D -> X-1.0.0那么A -> X-1.0.0这个版本 先声明优先范 ...

  3. java-反射和代理

    1.类的编译和运行简易过程: java的源码文件(也称为编译单元,以.java为后缀的文件) ↓ 文件内最多只能有一个public修饰的类,否则编译器报错:某个类被public修饰,该类名必需与文件名 ...

  4. 《Redis设计与实现》- AOF持久化

    1. AOF持久化 Redis AOF 持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的. 2. RDB持久化与AOF持久化的区别 RDB持久化 RDB持久化通过保存数据中的键值对来记 ...

  5. 【Effective C++ 读书笔记】导读 Introduction

    学习程序语言根本大法是一回事,学习如何以某种语言设计并实现高效程序则是另一回事. 一组明智选择并精心设计的classes.functions.templates可使程序编写容易.直观.高效.并且远离错 ...

  6. js开发中常用小技巧

    1.获取指定范围内的随机数 function getRadomNum(min,max){ return Math.floor(Math.random() * (max - min + 1)) + mi ...

  7. pc和移动端页面字体设置

    移动端项目:font-family:Tahoma,Arial,Roboto,”Droid Sans”,”Helvetica Neue”,”Droid Sans Fallback”,”Heiti SC” ...

  8. mysql 存储过程的基本语法知识

    1 MySQL中的基本的存储过程 我将其分类为增删改查来逐一的分布来说 增加: //创建一个存储过程 $sql = " CREATE PROCEDURE TABLE_PR2() ---- 注 ...

  9. Hive 文件格式 & Hive操作(外部表、内部表、区、桶、视图、索引、join用法、内置操作符与函数、复合类型、用户自定义函数UDF、查询优化和权限控制)

    本博文的主要内容如下: Hive文件存储格式 Hive 操作之表操作:创建外.内部表 Hive操作之表操作:表查询 Hive操作之表操作:数据加载 Hive操作之表操作:插入单表.插入多表 Hive语 ...

  10. wordCount的执行流程

    我们对于wordCount的这个流程,在清晰不过了,不过我们在使用spark以及hadoop本身的mapReduce的时候,我们是否理解其中的原理呢,今天我们就来介绍一下wordCount的执行原理, ...