题解

我们对于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」最短不公共子串的更多相关文章

  1. Loj #3056. 「HNOI2019」多边形

    Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...

  2. LOJ #2359. 「NOIP2016」天天爱跑步(倍增+线段树合并)

    题意 LOJ #2359. 「NOIP2016」天天爱跑步 题解 考虑把一个玩家的路径 \((x, y)\) 拆成两条,一条是 \(x\) 到 \(lca\) ( \(x, y\) 最近公共祖先) 的 ...

  3. luoguP4112 [HEOI2015]最短不公共子串 SAM,序列自动机,广搜BFS

    luoguP4112 [HEOI2015]最短不公共子串 链接 luogu loj 思路 子串可以用后缀自动机,子序列可以用序列自动机. 序列自动机是啥,就是能访问到所有子序列的自动机. 每个点记录下 ...

  4. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  5. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  6. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  7. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

  8. Loj #2542. 「PKUWC2018」随机游走

    Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...

  9. 【BZOJ4032】[HEOI2015]最短不公共子串(后缀自动机,序列自动机)

    [BZOJ4032][HEOI2015]最短不公共子串(后缀自动机,序列自动机) 题面 BZOJ 洛谷 题解 数据范围很小,直接暴力构建后缀自动机和序列自动机,然后直接在两个自动机上进行\(bfs\) ...

随机推荐

  1. python---基础知识回顾(十)进程和线程(进程)

    前戏:进程和线程的概念 若是学过linux下的进程,线程,信号...会有更加深刻的了解.所以推荐去学习下,包括网络编程都可以去了解,尤其是对select,poll,epoll都会有更多的认识. 进程就 ...

  2. 让你快速学会Shell脚本

    Shell脚本,就是利用Shell的命令解释的功能,对一个纯文本的文件进行解析,然后执行这些功能,也可以说Shell脚本就是一系列命令的集合.Shell可以直接使用在win/Unix/Linux上面, ...

  3. android 低功耗蓝牙使用

    参考链接:http://blog.csdn.net/xubin341719/article/details/38584469 1.android 手机的低功耗蓝牙,又称BLE :BLE在andriod ...

  4. 你需要了解 Windows Phone 8.1 的11件事

    微软已经发布了其新一代手机操作系统 Windows Phone 8.1,拥有一些新的特性.从本质上来说,微软此次的大修让 Windows Phone 更接近 Android 和 iOS,对于使用体验的 ...

  5. 巧妙使用CSS创建可以打印的页面

    用CSS创建打印页面,不必为打印而专门建立一个HTML文件,可以节省一些体力,其前提是按“WEB标准”用CSS+DIV布局HTML页面. 第一.在HTML页面加入为打印机设置的CSS文件 <li ...

  6. 【AtCoder】AGC005 F - Many Easy Problems 排列组合+NTT

    [题目]F - Many Easy Problems [题意]给定n个点的树,定义S为大小为k的点集,则f(S)为最小的包含点集S的连通块大小,求k=1~n时的所有点集f(S)的和取模92484403 ...

  7. HDU 6205 (模拟) card card card

    题目链接 Problem Description As a fan of Doudizhu, WYJ likes collecting playing cards very much. One day ...

  8. python加速包numba并行计算多线程

    1.下面直接上代码需要注意的地方numba的官网找到 1)有一些坑自己去numba的官网找找看,下面是我的写的一个加速的程序,希望对你有帮助. #coding:utf-8 import time fr ...

  9. 初时Python博大精深

    Python是解释型语言 编译型vs解释型 编译型优点:编译器一般会有预编译的过程对代码进行优化.因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高.可以脱离语言环境独立运行.缺点:编 ...

  10. 在Linode VPS上搭建最新版Transmission

    在Linode VPS上搭建最新版Transmission 2015-09-16 by Hansen 原文链接:http://www.hansendong.me/archives/124.html 以 ...