BZOJ4032 [HEOI2015]最短不公共子串 【后缀自动机 + 序列自动机 + dp】
题目链接
题解
首先膜\(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\)不选
\]
如果\(i\)被选,那么枚举是从哪一个节点转移来的
设上一个节点为\(u\)
\]
【注意这里是枚举\(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】的更多相关文章
- bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)
bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp) bzoj Luogu 题解时间 给两个小写字母串 $ A $ , $ B $ ,请你计算: ...
- BZOJ 4032: [HEOI2015]最短不公共子串 后缀自动机 暴力
4032: [HEOI2015]最短不公共子串 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4032 Description 在虐各种最 ...
- bzoj4032: [HEOI2015]最短不公共子串(SAM+DP)
4032: [HEOI2015]最短不公共子串 题目:传送门 题解: 陈年老题良心%你赛膜爆嘎爷 当初做题...一眼SAM...结果只会两种直接DP的情况... 情况1: 直接设f[i][j] 表示的 ...
- BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心
题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...
- BZOJ4032: [HEOI2015]最短不公共子串(后缀自动机+序列自动机)
题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...
- [BZOJ4032][HEOI2015]最短不公共子串(Trie+DP)
在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之——被它们虐. 操作一:对A,B分别建SAM,暴力BFS. 操作二:对B建序列自动机或SAM,A在上面暴力匹配. 操作三:对A,B建 ...
- BZOJ4032:[HEOI2015]最短不公共子串(SAM)
Description 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列” ...
- bzoj 4032 [HEOI2015]最短不公共子串——后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032 不是 b 的子串的话就对 b 建后缀自动机,在 a 上枚举从每个位置开始的子串或者找子 ...
- BZOJ 4032: [HEOI2015]最短不公共子串(后缀自动机+记忆化搜索)
传送门 解题思路 首先需要预处理两个串\(nxt(i)(j)\)表示i位置之后最近的\(j\). 第一问直接对\(b\)建后缀自动机,枚举\(a\)的起点暴力匹配. 第二问枚举\(a\)的起点,\(b ...
随机推荐
- WebSeal单点登陆
WebSeal单点登陆 作为学习整理,部分内容来自网络和官方文档. LDAP LDAP可以看作一种数据库,分为客户端和服务端.服务端是用来存放资源,客户端用来操作资源.它是一种树形存储结构,遍历起来会 ...
- BZOJ4128: Matrix(BSGS 矩阵乘法)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 813 Solved: 442[Submit][Status][Discuss] Descriptio ...
- docker基础——关于安装、常用指令以及镜像制作初体验
为什么使用docker docker就是一个轻量级的虚拟机,他解决的是服务迁移部署的时候环境配置问题.比如常见的web服务依赖于jdk.Tomcat.数据库等工具,迁移项目就需要在新的机器重新配置这些 ...
- linux定时任务及练习
第1章 定时任务 1.1 什么是定时任务 相当于闹钟每天叫你起床 设定一个时间去做某件事 1.2 系统定时任务 [root@zeq ~]# ll -d /etc/cron* drwxr-xr-x. 2 ...
- 类的特殊方法"__call__"详解
1. __call__ 当执行对象名+括号时, 会自动执行类中的"__call__"方法, 怎么用? class A: def __init__(self, name): self ...
- iOS-xib的使用1
一.File‘s owner的解析过程和使用: 1. storyboard:描述软件界面:iOS5.0后出来的. xib:描述软件界面:是storyboard前身. 2. 项目环境里面的所有资源都要通 ...
- linux select用法
select 是linux i/o 复用技术之一 man 2 select #include <sys/select.h> /* According to earlier standard ...
- C++基础 匿名对象
以下几种情况又会匿名对象 (1)对象构造 与 匿名对象 Test t1 = Test(); 这时,Test()会构造匿名对象,并且是调用无参构造函数,然后 t1 将匿名对象扶正. (2)对象赋值 与 ...
- POJ:2229-Sumsets(完全背包的优化)
题目链接:http://poj.org/problem?id=2229 Sumsets Time Limit: 2000MS Memory Limit: 200000K Total Submissio ...
- JDK及配置
Java Jdk开发时环境,程序员使用 Jre运行时环境,用户使用 Jdk的配置 1.新建java_home jdk的安装路径 例:C:\Program Files (x86)\Java\jdk1 ...