BZOJ4032: [HEOI2015]最短不公共子串(后缀自动机+序列自动机)
题目描述
在虐各种最长公共子串、子序列的题虐的不耐烦了之后,你决定反其道而行之。
一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是。
一个串的“子序列”指的是它的可以不连续的一段,例如bde是abcdef的子串,但bdd不是。
下面,给两个小写字母串A,B,请你计算:
(1) A的一个最短的子串,它不是B的子串
(2) A的一个最短的子串,它不是B的子序列
(3) A的一个最短的子序列,它不是B的子串
(4) A的一个最短的子序列,它不是B的子序列
输入输出格式
输入格式:
有两行,每行一个小写字母组成的字符串,分别代表A和B。
输出格式:
输出4行,每行一个整数,表示以上4个问题的答案的长度。如果没有符合要求的答案,输出-1.
输入输出样例
说明
对于20%的数据,A和B的长度都不超过20
对于50%的数据,A和B的长度都不超过500
对于100%的数据,A和B的长度都不超过2000
题解
这题好烦……
据说还有大佬是用dp的方法做的……相当于做了四道题……先膜为敬……
然后看到有大佬是直接建上后缀自动机和回文自动机,然后在上面跑BFS,如果跑不动了就返回答案,可以保证最优
然后我因为一堆sb错误调了一个多小时……
为啥取队头元素不能直接整个结构体取啊!为啥我SAM都能打错啊!
- //minamoto
- #include<cstring>
- #include<algorithm>
- #include<iostream>
- #include<cstdio>
- #include<queue>
- using namespace std;
- #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
- char buf[<<],*p1=buf,*p2=buf;
- char sr[<<],z[];int C=-,Z;
- inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
- inline void print(int x){
- if(C><<)Ot();if(x<)sr[++C]=,x=-x;
- while(z[++Z]=x%+,x/=);
- while(sr[++C]=z[Z],--Z);sr[++C]='\n';
- }
- const int N=;
- struct SAM{
- int fa[N],ch[N][],l[N];int last,cnt;
- SAM(){last=cnt=;}
- void ins(int c){
- int p=last,np=++cnt;last=np,l[np]=l[p]+;
- for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
- if(!p) fa[np]=;
- else{
- int q=ch[p][c];
- if(l[q]==l[p]+) fa[np]=q;
- else{
- int nq=++cnt;l[nq]=l[p]+;
- memcpy(ch[nq],ch[q],sizeof(ch[q]));
- fa[nq]=fa[q],fa[q]=fa[np]=nq;
- for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
- }
- }
- }
- }SA,SB;
- struct SqAM{
- int ch[N][],lst[],fa[N];
- int root,cnt;
- SqAM(){root=cnt=;for(int i=;i<;++i) lst[i]=;}
- void ins(int c){
- int p=lst[c],np=++cnt;
- fa[np]=p;
- for(int i=;i<;++i)
- for(int j=lst[i];j&&!ch[j][c];j=fa[j])
- ch[j][c]=np;
- lst[c]=np;
- }
- }SQA,SQB;
- struct node{
- int a,b,step;
- node(int a=,int b=,int step=):a(a),b(b),step(step){}
- };
- int vis[N][N];
- int bfs1(){
- queue<node> q;
- q.push(node(,,));
- vis[][]=;
- while(!q.empty()){
- int ra=q.front().a,rb=q.front().b,st=q.front().step;
- for(int i=;i<;i++){
- int va=SA.ch[ra][i],vb=SB.ch[rb][i];
- if(va&&vb){
- if(vis[va][vb]==) continue;
- q.push(node(va,vb,st+));
- vis[va][vb]=;
- }
- if(va&&!vb) return st+;
- }
- q.pop();
- }
- return -;
- }
- int bfs2(){
- queue<node> q;
- q.push(node(,,));
- vis[][]=;
- while(!q.empty()){
- int ra=q.front().a,rb=q.front().b,st=q.front().step;
- for(int i=;i<;i++){
- int va=SA.ch[ra][i],vb=SQB.ch[rb][i];
- if(va&&vb){
- if(vis[va][vb]==) continue;
- q.push(node(va,vb,st+));
- vis[va][vb]=;
- }
- if(va&&!vb) return st+;
- }
- q.pop();
- }
- return -;
- }
- int bfs3(){
- queue<node> q;
- q.push(node(,,));
- vis[][]=;
- while(!q.empty()){
- int ra=q.front().a,rb=q.front().b,st=q.front().step;
- for(int i=;i<;i++){
- int va=SQA.ch[ra][i],vb=SB.ch[rb][i];
- if(va&&vb){
- if(vis[va][vb]==) continue;
- q.push(node(va,vb,st+));
- vis[va][vb]=;
- }
- if(va&&!vb) return st+;
- }
- q.pop();
- }
- return -;
- }
- int bfs4(){
- queue<node> q;
- q.push(node(,,));
- vis[][]=;
- while(!q.empty()){
- int ra=q.front().a,rb=q.front().b,st=q.front().step;
- for(int i=;i<;i++){
- int va=SQA.ch[ra][i],vb=SQB.ch[rb][i];
- if(va&&vb){
- if(vis[va][vb]==) continue;
- q.push(node(va,vb,st+));
- vis[va][vb]=;
- }
- if(va&&!vb) return st+;
- }
- q.pop();
- }
- return -;
- }
- char a[N],b[N];int tot1,tot2;char ch;
- int main(){
- scanf("%s%s",a+,b+);
- tot1=strlen(a+),tot2=strlen(b+);
- for(int i=;i<=tot1;++i) SA.ins(a[i]-'a'),SQA.ins(a[i]-'a');
- for(int i=;i<=tot2;++i) SB.ins(b[i]-'a'),SQB.ins(b[i]-'a');
- printf("%d\n%d\n%d\n%d\n",bfs1(),bfs2(),bfs3(),bfs4());
- return ;
- }
BZOJ4032: [HEOI2015]最短不公共子串(后缀自动机+序列自动机)的更多相关文章
- 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】
题目链接 BZOJ4032 题解 首先膜\(hb\) 空手切神题 一问\(hash\),二问枚举 三问\(trie\)树,四问\(dp\) 南二巨佬神\(hb\) 空手吊打自动机 \(orz orz ...
- BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心
题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如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 ...
随机推荐
- 文件 md5 查看 命令
Windows命令查看文件MD5 certutil -hashfile yourfilename.ext MD5 certutil -hashfile yourfilename.ext SHA1 ...
- python's metaclass
[python's metaclass] 和objc中类似,metaclass用于创建一个类对象,但与objc不同的是,objc中每个类对象有各自不同的metaclass,而python中的metac ...
- 阿里云 mysql 远程登录权限
[mysql中配置] 授权法: 1.登录到mysql中,为root进行远程访问的授权,执行下面的命令: mysql> GRANT ALL PRIVILEGES ON *.* TO root@& ...
- nodejs中yield的用法?
nodejs中yield的用法? https://www.zhihu.com/question/32752866?sort=created
- OSG QT
https://blog.csdn.net/a_Treasure/article/details/82152245 https://www.bbsmax.com/A/kPzOQ4oo5x/ https ...
- Linux Virtualization with Xen
Xen is the new virtualization kid on the block. It's gaining visibility and importance at a speed on ...
- 4418开发板读取u盘说明
1.插上u盘后会在dev下生成两个文件db db1 将db1挂载即可访问..
- ubuntu14.04 64位安装 g2o
参考链接:http://blog.csdn.net/jiujiu932/article/details/52248577 http://www.cnblogs.com/gaoxiang12/p/473 ...
- CENTOS 使用 MUTT发送邮件
有些时候我们需要在Centos服务器上发送邮件,例如备份MySQL数据库并发送到指定邮箱,这里我们就说下如何从Centos的shell命令发送邮件. 检查.安装.启动sendmail //检查 ps ...
- 编写高质量代码改善C#程序的157个建议——建议102:区分接口和抽象类的应用场合
建议102:区分接口和抽象类的应用场合 接口和抽象类有一些显而易见的区别: 接口支持多继承,抽象类则不能. 接口可以包含方法.属性.索引器.事件的签名,但不能有实现,抽象类则可以. 接口在增加新方法后 ...