4032: [HEOI2015]最短不公共子串

题目连接:

http://www.lydsy.com/JudgeOnline/problem.php?id=4032

Description

在虐各种最长公共子串、子序列的题虐的不耐烦了之后,你决定反其道而行之。

一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是。

一个串的“子序列”指的是它的可以不连续的一段,例如bde是abcdef的子串,但bdd不是。

下面,给两个小写字母串A,B,请你计算:

(1) A的一个最短的子串,它不是B的子串

(2) A的一个最短的子串,它不是B的子序列

(3) A的一个最短的子序列,它不是B的子串

(4) A的一个最短的子序列,它不是B的子序列

Input

有两行,每行一个小写字母组成的字符串,分别代表A和B。

Output

输出4行,每行一个整数,表示以上4个问题的答案的长度。如果没有符合要求的答案,输出-1.

Sample Input

aabbcc

abcabc

Sample Output

2

4

2

4

Hint

对于100%的数据,A和B的长度都不超过2000

题意

题解:

bfs四合一

答案都是最长公共子XX+1

子串我们用后缀自动机去跑,子序列我们用dp的贪心去跑就好了

那个dp表示从i位置走到字符j的最小位置

注意后缀自动机要开两倍空间……因为这个,wa成傻逼了

代码

#include<bits/stdc++.h>
using namespace std; const int maxn = 2e3+5;
char s1[maxn],s2[maxn];
int len1,len2;
int go1[maxn][26],go2[maxn][26];
int vis[maxn][maxn*2];
int Son[maxn*2][26],pre[maxn*2],len[maxn*2],la=1,Now=1;
struct SAM
{
void add(int x)
{
int p=la,np=la=++Now;
len[np]=len[p]+1;
for(;p&&!Son[p][x];p=pre[p])
Son[p][x]=np;
if(!p)
pre[np]=1;
else
{
int q=Son[p][x];
if(len[q]==len[p]+1)
pre[np]=q;
else
{
int nq=++Now;
memcpy(Son[nq],Son[q],sizeof Son[nq]);
len[nq]=len[p]+1;
pre[nq]=pre[q];
pre[q]=pre[np]=nq;
for(;p&&Son[p][x]==q;p=pre[p])
Son[p][x]=nq;
}
}
}
}sam; struct node
{
int x,y,l;
};
queue<node>Q;
void init()
{
memset(vis,0,sizeof(vis));
while(!Q.empty())Q.pop();
}
int solve1()
{
init();
for(int i=0;i<len1;i++)
Q.push(node{i,1,0});
while(!Q.empty())
{
node Now = Q.front();
Q.pop();
if(Now.x==len1)continue;
int nextx=Now.x+1,nexty=Son[Now.y][s1[nextx]-'a'];
if(nexty==0)return Now.l+1;
if(!vis[nextx][nexty])
vis[nextx][nexty]=1,Q.push(node{nextx,nexty,Now.l+1});
}
return -1;
}
int solve2()
{
init();
for(int i=0;i<len1;i++)
Q.push(node{i,0,0});
while(!Q.empty())
{
node Now = Q.front();
Q.pop();
if(Now.x==len1)continue;
int nextx=Now.x+1,nexty=go2[Now.y][s1[Now.x+1]-'a'];
if(nexty==1e5)return Now.l+1;
if(!vis[nextx][nexty])
vis[nextx][nexty]=1,Q.push(node{nextx,nexty,Now.l+1});
}
return -1;
}
int solve3()
{
init();
Q.push(node{0,1,0});
while(!Q.empty())
{
node Now = Q.front();
Q.pop();
for(int i=0;i<26;i++)
{
int nextx=go1[Now.x][i],nexty=Son[Now.y][s1[nextx]-'a'];
if(nextx==1e5)continue;
if(nexty==0)return Now.l+1;
if(!vis[nextx][nexty])
vis[nextx][nexty]=1,Q.push(node{nextx,nexty,Now.l+1});
}
}
return -1;
}
int solve4()
{
init();
Q.push(node{0,0,0});
while(!Q.empty())
{
node Now = Q.front();
Q.pop();
for(int i=0;i<26;i++)
{
int nextx=go1[Now.x][i],nexty=go2[Now.y][i];
if(nextx==1e5)continue;
if(nexty==1e5)return Now.l+1;
if(!vis[nextx][nexty])
vis[nextx][nexty]=1,Q.push(node{nextx,nexty,Now.l+1});
}
}
return -1;
}
int main()
{
scanf("%s%s",s1+1,s2+1);
len1=strlen(s1+1),len2=strlen(s2+1);
for(int i=1;i<=len2;i++)sam.add(s2[i]-'a');
for(int i=0;i<maxn;i++)for(int j=0;j<26;j++)
go1[i][j]=go2[i][j]=1e5;
for(int i=0;i<=len1;i++)
for(int j=i+1;j<=len1;j++)
go1[i][s1[j]-'a']=min(go1[i][s1[j]-'a'],j);
for(int i=0;i<=len2;i++)
for(int j=i+1;j<=len2;j++)
go2[i][s2[j]-'a']=min(go2[i][s2[j]-'a'],j);
printf("%d\n%d\n%d\n%d\n",solve1(),solve2(),solve3(),solve4());
}

BZOJ 4032: [HEOI2015]最短不公共子串 后缀自动机 暴力的更多相关文章

  1. bzoj 4032 [HEOI2015]最短不公共子串——后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032 不是 b 的子串的话就对 b 建后缀自动机,在 a 上枚举从每个位置开始的子串或者找子 ...

  2. BZOJ 4032: [HEOI2015]最短不公共子串(后缀自动机+记忆化搜索)

    传送门 解题思路 首先需要预处理两个串\(nxt(i)(j)\)表示i位置之后最近的\(j\). 第一问直接对\(b\)建后缀自动机,枚举\(a\)的起点暴力匹配. 第二问枚举\(a\)的起点,\(b ...

  3. bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)

    bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp) bzoj Luogu 题解时间 给两个小写字母串 $ A $ , $ B $ ,请你计算: ...

  4. BZOJ 4032: [HEOI2015]最短不公共子串

    4032: [HEOI2015]最短不公共子串 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 446  Solved: 224[Submit][Sta ...

  5. BZOJ.4032.[HEOI2015]最短不公共子串(DP 后缀自动机)

    题目链接 1.求A的最短子串,它不是B的子串. 子串是连续的,对B建SAM,枚举起点,在SAM上找到第一个无法匹配点即可.O(n)用SAM能做吗..开始想错了. 2.求A的最短子串,它不是B的子序列. ...

  6. bzoj 4032: [HEOI2015]最短不公共子串【dp+SAM】

    第一.二问: 就是最小的最长公共长度+1,设f[i][j]为a匹配到i,b匹配到j,第一问的转移是f[i][j]=(a[i]==b[j]?f[i-1][j-1]+1:0),第二问的转移是f[i][j] ...

  7. BZOJ 4032: [HEOI2015]最短不公共子串 (dp*3 + SAM)

    转博客大法好 第4个子任务中,为什么只转移最近的一个位置,自己YY吧(多YY有益身体健康). #include <bits/stdc++.h> using namespace std; t ...

  8. bzoj 4032 [ HEOI 2015 ] 最短不公共子串 —— 后缀自动机+序列自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032 序列自动机其实就是每个位置记录一下某字母后面第一个出现位置,为了子序列能尽量长. 对字 ...

  9. 【BZOJ】4032: [HEOI2015]最短不公共子串(LibreOJ #2123)

    [题意]给两个小写字母串A,B,请你计算: (1) A的一个最短的子串,它不是B的子串 (2) A的一个最短的子串,它不是B的子序列 (3) A的一个最短的子序列,它不是B的子串 (4) A的一个最短 ...

随机推荐

  1. Java 关于微信公众号支付总结附代码

    很多朋友第一次做微信支付的时候都有蒙,但当你完整的做一次就会发现其实并没有那么难 业务流程和应用场景官网有详细的说明:https://pay.weixin.qq.com/wiki/doc/api/js ...

  2. 【hihocoder】sam-3

    把Parent Tree拓扑排序下,然后从下往上合并. 具体的看官方题解啦~ #include<bits/stdc++.h> #define N 1000010 using namespa ...

  3. 2014ACM/ICPC亚洲区北京站题解

    本题解不包括个人觉得太水的题(J题本人偷懒没做). 个人觉得这场其实HDU-5116要比HDU-5118难,不过赛场情况似乎不是这样.怀疑是因为老司机带错了路. 这套题,个人感觉动态规划和数论是两个主 ...

  4. C基础 常用设计模式粗解

    引言 面向对象, 设计模式是现代软件开发基石. C的面向过程已经很简洁, 但不代表C就没有面向对象.(libuv框架中C面向对象用的很多) 因为思想是互通的.全当熟悉一下那些常用的设计模式.先假定有一 ...

  5. 解决Mac开机变慢 command +option + P + R

    Mac开机变慢怎么办? command +option + P + R 重点是 开机 后 一直按 该4个键不放  听到3声音响 屏幕出现灰暗灰暗几次 开机速度 5s 重置PRAM和NVRAM的方法都是 ...

  6. [New Learn] RunLoop学习-官方译文

    Run Loops Run loops是线程的一个基本构成部分.一个run loop 是一个事件处理循环,你可以使用它来处理线程收到的事件.设计run loop的目的就是可以使得线程在收到事件的时候处 ...

  7. 12-6 NSArray

    原文:http://rypress.com/tutorials/objective-c/data-types/nsarray NSArray NSArray 是 Objective-C中最常用的数组类 ...

  8. FineReport——JS二次开发(下拉框)

    下拉框显示多列时,输入的内容检索的内容为显示值整行数据,而不是实际值. 下拉框选择之后,控件显示的是显示值而非实际值. 对于下拉框显示队列,可以有多种方法,但是经过测试大多数方法不适用,检索效率太低, ...

  9. mui 怎样监听scroll事件的滚动距离

    var scroll = mui('.mui-scroll-wrapper').scroll(); document.querySelector('.mui-scroll-wrapper' ).add ...

  10. [转载] Python itertools模块详解

    原文在这里,写的很详细,感谢原作者,以下摘录要点. itertools用于高效循环的迭代函数集合. 无限迭代器 迭代器 参数 结果 例子 count() start, [step] start, st ...