【LOJ】#2123. 「HEOI2015」最短不公共子串
题解
我们对于B串建出后缀自动机和序列自动机
对于问题1,枚举左端点然后跑后缀自动机,直到不能匹配作为这个左端点的答案
对于问题2,枚举左端点然后跑序列自动机,直到不能匹配
对于问题3,设f[i][j]表示第前i个字符匹配到后缀自动机上第j个点的最少步数,如果下一步走不了则更新答案
对于问题4,设f[i][j]表示前i个字符匹配到序列自动机上第j个点的最少步数,如果下一步走不了则更新答案
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#define enter putchar('\n')
#define space putchar(' ')
//#define ivorysi
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 1000000007;
char A[2005],B[2005];
int LA,LB;
int f[2005][4005];
struct SuffixAutoMaton{
struct SAM_node {
SAM_node *par,*nxt[26];
int len;
SAM_node *find_next(char c) {
if(nxt[c - 'a']) return nxt[c - 'a'];
else return NULL;
}
}pool[4005],*tail = pool,*root,*last;
SuffixAutoMaton() {
root = last = tail++;
}
void build(int l,int e) {
SAM_node *nowp = tail++,*p;
nowp->len = l;
for(p = last ; p && !p->nxt[e]; p = p->par) {
p->nxt[e] = nowp;
}
if(!p) nowp->par = root;
else {
SAM_node *q = p->nxt[e];
if(q->len == p->len + 1) nowp->par = q;
else {
SAM_node *copyq = tail++;
*copyq = *q;
copyq->len = p->len + 1;
q->par = nowp->par = copyq;
for( ; p && p->nxt[e] == q ; p = p->par) {
p->nxt[e] = copyq;
}
}
}
last = nowp;
}
int calc1(int st) {
SAM_node *p = root;
int res = 0;
for(int i = st ; i <= LA ; ++i) {
p = p->find_next(A[i]);
if(!p) break;
++res;
}
if(res == LA - st + 1) return LA + 1;
return res + 1;
}
int calc3() {
int m = tail - pool;
for(int i = 0 ; i <= LA ; ++i) {
for(int j = 1 ; j <= m ; ++j) {
f[i][j] = 0x7fffffff;
}
}
f[0][1] = 0;
int res = LA + 1;
for(int i = 1 ; i <= LA ; ++i) {
for(int j = 1 ; j <= m ; ++j) {
if(f[i - 1][j] != 0x7fffffff) {
f[i][j] = min(f[i - 1][j],f[i][j]);
SAM_node *p = pool[j - 1].find_next(A[i]);
if(!p) res = min(res,f[i - 1][j] + 1);
else f[i][p - pool + 1] = min(f[i][p - pool + 1],f[i][j] + 1);
}
}
}
return res;
}
}SAM;
struct LineAutoMaton {
int ch[2005][26],head[30],next[2005],tot,rt;
LineAutoMaton() {
rt = tot = 1;
for(int i = 0 ; i < 26 ; ++i) head[i] = 1;
}
void build(char c) {
++tot;next[tot] = head[c - 'a'];
for(int i = 0 ; i < 26 ; ++i) {
for(int j = head[i] ; j ; j = next[j]) {
if(!ch[j][c - 'a']) ch[j][c - 'a'] = tot;
else break;
}
}
head[c - 'a'] = tot;
}
int calc2(int st) {
int p = rt,L = 0;
for(int i = st ; i <= LA ; ++i) {
if(ch[p][A[i] - 'a']) {
p = ch[p][A[i] - 'a'];
++L;
}
else break;
}
if(L == LA - st + 1) return LA + 1;
return L + 1;
}
int calc4() {
for(int i = 0 ;i <= LA ; ++i) {
for(int j = 1 ; j <= tot ; ++j) {
f[i][j] = 0x7fffffff;
}
}
f[0][1] = 0;
int res = LA + 1;
for(int i = 1 ; i <= LA ; ++i) {
for(int j = 1 ; j <= tot ; ++j) {
if(f[i - 1][j] != 0x7fffffff) {
f[i][j] = min(f[i - 1][j],f[i][j]);
int p = ch[j][A[i] - 'a'];
if(!p) res = min(res,f[i - 1][j] + 1);
else f[i][p] = min(f[i - 1][j] + 1,f[i][p]);
}
}
}
return res;
}
}LAM;
void Init() {
scanf("%s",A + 1);
scanf("%s",B + 1);
LA = strlen(A + 1);LB = strlen(B + 1);
for(int i = 1 ; i <= LB ; ++i) {
SAM.build(i,B[i] - 'a');
LAM.build(B[i]);
}
}
void Solve1() {
int ans = LA + 1;
for(int i = 1 ; i <= LA ; ++i) {
ans = min(ans,SAM.calc1(i));
}
if(ans > LA) puts("-1");
else {out(ans),enter;}
}
void Solve2() {
int ans = LA + 1;
for(int i = 1 ; i <= LA ; ++i) {
ans = min(ans,LAM.calc2(i));
}
if(ans > LA) puts("-1");
else out(ans),enter;
}
void Solve3() {
int ans = SAM.calc3();
if(ans > LA) puts("-1");
else out(ans),enter;
}
void Solve4() {
int ans = LAM.calc4();
if(ans > LA) puts("-1");
else out(ans),enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve1();
Solve2();
Solve3();
Solve4();
}
【LOJ】#2123. 「HEOI2015」最短不公共子串的更多相关文章
- Loj #3056. 「HNOI2019」多边形
Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...
- LOJ #2359. 「NOIP2016」天天爱跑步(倍增+线段树合并)
题意 LOJ #2359. 「NOIP2016」天天爱跑步 题解 考虑把一个玩家的路径 \((x, y)\) 拆成两条,一条是 \(x\) 到 \(lca\) ( \(x, y\) 最近公共祖先) 的 ...
- luoguP4112 [HEOI2015]最短不公共子串 SAM,序列自动机,广搜BFS
luoguP4112 [HEOI2015]最短不公共子串 链接 luogu loj 思路 子串可以用后缀自动机,子序列可以用序列自动机. 序列自动机是啥,就是能访问到所有子序列的自动机. 每个点记录下 ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Loj #3096. 「SNOI2019」数论
Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...
- Loj #3093. 「BJOI2019」光线
Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...
- Loj #3089. 「BJOI2019」奥术神杖
Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...
- Loj #2542. 「PKUWC2018」随机游走
Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...
- 【BZOJ4032】[HEOI2015]最短不公共子串(后缀自动机,序列自动机)
[BZOJ4032][HEOI2015]最短不公共子串(后缀自动机,序列自动机) 题面 BZOJ 洛谷 题解 数据范围很小,直接暴力构建后缀自动机和序列自动机,然后直接在两个自动机上进行\(bfs\) ...
随机推荐
- IOS TableView滑动不灵敏问题
TableView的默认的不常用的属性,我们尽量不要去改,如下面标注的几个
- 科学计算三维可视化---Mlab基础(鼠标选取交互操作)
一:鼠标选取介绍 二:选取红色小球分析 相关方法:科学计算三维可视化---Mlab基础(基于Numpy数组的绘图函数) 1.小球场景初始化建立 import numpy as np from maya ...
- python---web微信开发
一:轮询,长轮询,WebSocket了解 轮询: 在前端,设置时间内,一直向后端发送请求.例如:使用setInterval方法设置定时器,一秒向后端发送一次请求,去主动获取数据,进行更新由于前端一直请 ...
- MongoDB - MongoDB CRUD Operations, Bulk Write Operations
Overview MongoDB provides clients the ability to perform write operations in bulk. Bulk write operat ...
- idea绘制activity流程图中文乱码解决
发现问题: 绘制activity的bpm工作流程图的时候,在name项中填写中文,开始的时候没问题,显示的确是中文,关闭文件再打开发现已经乱码,重启idea效果相同,如图 解决方案:修改idea启动参 ...
- spring——IOC容器BeanFactory和ApplicationContext对比
- python核心编程笔记——Chapter8
Chapter8.条件和循环 这一章感觉有用的点并不多,在我眼里就只有迭代器,列表解析和生成器表达式值得研究而已. 8.2.循环,难度不大. #!usr/bin/env python #-*-codi ...
- shell操作典型案例--FTP操作
从FTP服务器上下载文件或上传文件到FTP服务器是生产环境中比较常见的场景之一. shell操作FTP的方式整理如下: 思路一:使用shell调用ftp等客户端 使用FTP方式,通过shell调用ft ...
- HDU 3065 病毒侵袭持续中 (AC自动机)
题目链接 Problem Description 小t非常感谢大家帮忙解决了他的上一个问题.然而病毒侵袭持续中.在小t的不懈努力下,他发现了网路中的"万恶之源".这是一个庞大的病毒 ...
- Python练习-一个Break跳出所有循环
Alex大神的需求:三层循环,在最内层循环中使用break,让所有循环结束; # 编辑者:闫龙 i=1; count=0; while 1==i : while 1==i: while 1==i: c ...