【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\) ...
随机推荐
- 2017 清北济南考前刷题Day 7 morning
期望得分:100+50+20=170 实际得分:10+50+20=80 1. 纸牌 题目描述 在桌面上放着n张纸牌,每张纸牌有两面,每面都写着一个非负整数.你的邪王真眼可以看到所有牌朝上的一面和朝下的 ...
- PHP远程连接mysql报错处理办法
在万网弄了个虚拟主机,想远程连mysql调试(本地4G如果开mysql内存不够!),一直报错: mysqlnd cannot connect to MySQL 4.1+ using the old i ...
- jquery如何获取input(file)控件上传的图片名称,即"11111.jpg"
html代码:<input name=file" type="file" id="file"/> Jquery代码:var file;$( ...
- [整理]Node入门 » 一本全面的Node.js教程 - Demo实践所遇到的问题
花了一个上午看完[转载]Node入门 » 一本全面的Node.js教程 根据里面的Demo自己手动实现过程中还是遇到了些问题,特整理在此. <1>.由于node.msi安装包已经自动添加了 ...
- Web开发中的18个关键性错误
前几年,我有机会能参与一些有趣的项目,并且独立完成开发.升级.重构以及新功能的开发等工作. 本文总结了一些PHP程序员在Web开发中经常 忽略的关键错误,尤其是在处理中大型的项目上问题更为突出.典型的 ...
- 【AtCoder Grand Contest 001F】Wide Swap [线段树][拓扑]
Wide Swap Time Limit: 50 Sec Memory Limit: 512 MB Description Input Output Sample Input 8 3 4 5 7 8 ...
- HDU 2094 产生冠军 dfs加map容器
解题报告:有一群人在打乒乓球比赛,需要在这一群人里面选出一个冠军,现在规定,若a赢了b,b又赢了c那么如果a与c没有比赛的话,就默认a赢了c,而如果c赢了a的话,则这三个人里面选不出冠军,还有就是如果 ...
- Multidimensional Queries(二进制枚举+线段树+Educational Codeforces Round 56 (Rated for Div. 2))
题目链接: https://codeforces.com/contest/1093/problem/G 题目: 题意: 在k维空间中有n个点,每次给你两种操作,一种是将某一个点的坐标改为另一个坐标,一 ...
- MySQL5.7之多源复制&Nginx中间件(下)【转】
有生之年系列----MySQL5.7之多源复制&Nginx中间件(下)-wangwenan6-ITPUB博客http://blog.itpub.net/29510932/viewspace-1 ...
- 004_MAC实用的小工具
一.XtraFinder(右键菜单扩展) http://www.xuebuyuan.com/173454.html http://www.mamicode.com/info-detail-111618 ...