好像序列自动机还没有写过…

串长为n的串共有n+1个节点,除了串中的n个节点,还有一个空的根节点放在串首。每个节点至多有26条出边,每条边连向它之后的第一个字符。

串中的任意一个子序列对应了一条根到某个节点的路径。且每条路径对应一个不同的子序列。

每个节点的parent是这个字母上一次出现的位置。更新只要沿parent指针扫描即可。

FJOI2016 所有公共子序列问题

这题暴力建trie能过80真是悲伤(因为按FJOI命题风格这题没有写数据范围

建完序列自动机暴力DP即可

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <limits>
#include <set>
#include <map>
using namespace std;
#define SZ 3333
int ys[2333],fys[2333];
#define M 60
struct Seq_A_M
{
int par[SZ],ch[SZ][62],lst[62],C,rot;
Seq_A_M()
{
C=rot=1;
for(int i=0;i<M;i++) lst[i]=rot;
}
void ins(char c)
{
++C; par[C]=lst[c];
for(int i=0;i<M;i++)
{
for(int g=lst[i];g&&!ch[g][c];g=par[g]) ch[g][c]=C;
}
lst[c]=C;
}
}S_A,S_B;
int n,m;
typedef long long ll;
ll dp[SZ][SZ];
char x[SZ],y[SZ];
ll getdp(int a,int b)
{
if(!a||!b) return 0;
if(dp[a][b]>=0) return dp[a][b];
long long ans=1;
for(int i=0;i<M;i++) ans+=getdp(S_A.ch[a][i],S_B.ch[b][i]);
return dp[a][b]=ans;
}
char s[233333];
void tryy(int a,int b,int cl)
{
if(!a||!b) return;
s[cl]=0; printf("%s\n",s);
for(int i=0;i<M;i++)
{
s[cl]=fys[i]; tryy(S_A.ch[a][i],S_B.ch[b][i],cl+1);
}
}
int main()
{
for(int i='A';i<='Z';i++) ys[i]=i-'A', fys[i-'A']=i;
for(int i='a';i<='z';i++) ys[i]=i-'a'+26, fys[i-'a'+26]=i;
int k=0;
scanf("%d%d%s%s%d",&n,&m,x,y,&k);
for(int i=0;i<n;i++) S_A.ins(ys[x[i]]);
for(int i=0;i<m;i++) S_B.ins(ys[y[i]]);
if(k==1) tryy(1,1,0);
memset(dp,-1,sizeof(dp));
printf("%lld\n",getdp(1,1));
}

四校联考 公共串问题

还是暴力DP。注意一些细节。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <limits>
#include <set>
#include <map>
using namespace std;
int MOD=998244353;
#define SZ 4008
#define S 26 //字符集
struct AM
{
int rot,ch[SZ][S],C,cnt[SZ];
};
struct SeqAM: public AM
{
int par[SZ],lst[S];
SeqAM()
{
C=rot=1;
for(int i=0;i<S;i++) lst[i]=rot;
}
void ins(char c)
{
++C; par[C]=lst[c];
for(int i=0;i<S;i++)
{
for(int g=lst[i];g&&!ch[g][c];g=par[g]) ch[g][c]=C;
}
lst[c]=C;
}
void getcnt()
{
for(int i=1;i<=C;i++) cnt[i]=1;
for(int i=C;i>=1;i--)
{
for(int j=0;j<S;j++) cnt[i]+=cnt[ch[i][j]], cnt[i]%=MOD;
}
}
}SeqA,SeqB;
struct SufAM: public AM
{
int ml[SZ],fail[SZ],lst,cl,qzh[SZ],od[SZ];
SufAM() {C=lst=rot=1; cl=0;}
void ins(char c)
{
int x=++C,len=++cl,p=lst;
lst=x; ml[x]=len;
for(;p&&!ch[p][c];p=fail[p]) ch[p][c]=x;
if(!p) fail[x]=rot;
else if(ml[ch[p][c]]==ml[p]+1) fail[x]=ch[p][c];
else
{
int chh=ch[p][c],cm=++C;
ml[cm]=ml[p]+1; fail[cm]=fail[chh];
for(int i=0;i<S;i++) ch[cm][i]=ch[chh][i];
fail[chh]=fail[x]=cm;
for(;ch[p][c]==chh;p=fail[p]) ch[p][c]=cm;
}
}
void getcnt()
{
for(int i=0;i<SZ;i++) qzh[i]=0;
for(int i=1;i<=C;i++) qzh[ml[i]]++;
for(int i=1;i<SZ;i++) qzh[i]+=qzh[i-1];
for(int i=1;i<=C;i++) od[qzh[ml[i]]--]=i;
for(int i=1;i<=C;i++) cnt[i]=1;
for(int i=C;i>=1;i--)
{
for(int j=0;j<S;j++) cnt[od[i]]+=cnt[ch[od[i]][j]], cnt[od[i]]%=MOD;
}
}
}SufA,SufB;
void prtat(AM& s)
{
for(int i=1;i<=s.C;i++)
{
for(int j=0;j<S;j++) if(s.ch[i][j]) printf("%d->%d[label=%c];\n",i,s.ch[i][j],j+'a');
}
}
AM *cur,*curb;
int dp2[SZ][SZ];
int dfs(int a,int b)
{
if(!a) return 0;
if(!b) return cur->cnt[a];
if(dp2[a][b]>=0) return dp2[a][b];
int ans=0;
for(int i=0;i<S;i++) ans+=dfs(cur->ch[a][i],curb->ch[b][i]), ans%=MOD;
return dp2[a][b]=ans;
}
int getdp(AM& a,AM& b)
{
cur=&a; curb=&b;
for(int i=1;i<=a.C;i++)
for(int j=1;j<=b.C;j++) dp2[i][j]=-1;
dfs(a.rot,b.rot);
return dp2[a.rot][b.rot];
}
char A[SZ],B[SZ];
void prt(int a)
{
a=(a%MOD+MOD)%MOD;
printf("%d\n",a);
}
int main()
{
scanf("%s%s",A,B);
for(int i=0;A[i];i++) SeqA.ins(A[i]-'a'), SufA.ins(A[i]-'a');
for(int i=0;B[i];i++) SeqB.ins(B[i]-'a'), SufB.ins(B[i]-'a');
SeqA.getcnt(); SeqB.getcnt();
SufA.getcnt(); SufB.getcnt();
int AseqBseq=getdp(SeqA,SeqB);
int AseqBsuf=getdp(SeqA,SufB);
int AsufBseq=getdp(SufA,SeqB);
int AsufBsuf=getdp(SufA,SufB);
prt(AsufBsuf);
prt(AsufBseq);
prt(AseqBsuf);
prt(AseqBseq);
}

bzoj4032 最短不公共子串

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <limits>
#include <set>
#include <map>
using namespace std;
int MOD=998244353;
#define SZ 4008
#define S 26 //字符集
struct AM
{
int rot,ch[SZ][S],C,cnt[SZ];
};
struct SeqAM: public AM
{
int par[SZ],lst[S];
SeqAM()
{
C=rot=1;
for(int i=0;i<S;i++) lst[i]=rot;
}
void ins(char c)
{
++C; par[C]=lst[c];
for(int i=0;i<S;i++)
{
for(int g=lst[i];g&&!ch[g][c];g=par[g]) ch[g][c]=C;
}
lst[c]=C;
}
void getcnt()
{
for(int i=1;i<=C;i++) cnt[i]=1;
for(int i=C;i>=1;i--)
{
for(int j=0;j<S;j++) cnt[i]+=cnt[ch[i][j]], cnt[i]%=MOD;
}
}
}SeqA,SeqB;
struct SufAM: public AM
{
int ml[SZ],fail[SZ],lst,cl,qzh[SZ],od[SZ];
SufAM() {C=lst=rot=1; cl=0;}
void ins(char c)
{
int x=++C,len=++cl,p=lst;
lst=x; ml[x]=len;
for(;p&&!ch[p][c];p=fail[p]) ch[p][c]=x;
if(!p) fail[x]=rot;
else if(ml[ch[p][c]]==ml[p]+1) fail[x]=ch[p][c];
else
{
int chh=ch[p][c],cm=++C;
ml[cm]=ml[p]+1; fail[cm]=fail[chh];
for(int i=0;i<S;i++) ch[cm][i]=ch[chh][i];
fail[chh]=fail[x]=cm;
for(;ch[p][c]==chh;p=fail[p]) ch[p][c]=cm;
}
}
void getcnt()
{
for(int i=0;i<SZ;i++) qzh[i]=0;
for(int i=1;i<=C;i++) qzh[ml[i]]++;
for(int i=1;i<SZ;i++) qzh[i]+=qzh[i-1];
for(int i=1;i<=C;i++) od[qzh[ml[i]]--]=i;
for(int i=1;i<=C;i++) cnt[i]=1;
for(int i=C;i>=1;i--)
{
for(int j=0;j<S;j++) cnt[od[i]]+=cnt[ch[od[i]][j]], cnt[od[i]]%=MOD;
}
}
}SufA,SufB;
void prtat(AM& s)
{
for(int i=1;i<=s.C;i++)
{
for(int j=0;j<S;j++) if(s.ch[i][j]) printf("%d->%d[label=%c];\n",i,s.ch[i][j],j+'a');
}
}
int dep[SZ][SZ];
int qa[SZ*SZ],qb[SZ*SZ];
int bfs(AM& a,AM& b)
{
memset(dep,0,sizeof(dep));
int h=0,t=1; qa[0]=a.rot; qb[0]=b.rot; dep[qa[0]][qb[0]]=1;
while(h!=t)
{
int ca=qa[h],cb=qb[h]; ++h;
for(int j=0;j<S;j++)
{
int _ca=a.ch[ca][j],_cb=b.ch[cb][j];
if(dep[_ca][_cb]||!_ca) continue;
if(!_cb) return dep[ca][cb];
dep[_ca][_cb]=dep[ca][cb]+1;
qa[t]=_ca; qb[t]=_cb; ++t;
}
}
return -1;
}
#define prt(x) printf("%d\n",x)
char A[SZ],B[SZ];
int main()
{
scanf("%s%s",A,B);
for(int i=0;A[i];i++) SeqA.ins(A[i]-'a'), SufA.ins(A[i]-'a');
for(int i=0;B[i];i++) SeqB.ins(B[i]-'a'), SufB.ins(B[i]-'a');
SeqA.getcnt(); SeqB.getcnt();
SufA.getcnt(); SufB.getcnt();
int AseqBseq=bfs(SeqA,SeqB);
int AseqBsuf=bfs(SeqA,SufB);
int AsufBseq=bfs(SufA,SeqB);
int AsufBsuf=bfs(SufA,SufB);
prt(AsufBsuf);
prt(AsufBseq);
prt(AseqBsuf);
prt(AseqBseq);
}

后缀自动机&序列自动机综合的更多相关文章

  1. BZOJ4032 [HEOI2015]最短不公共子串 【后缀自动机 + 序列自动机 + dp】

    题目链接 BZOJ4032 题解 首先膜\(hb\) 空手切神题 一问\(hash\),二问枚举 三问\(trie\)树,四问\(dp\) 南二巨佬神\(hb\) 空手吊打自动机 \(orz orz ...

  2. 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做

    题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...

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

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

  4. BZOJ4032: [HEOI2015]最短不公共子串(后缀自动机+序列自动机)

    题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...

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

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

  6. BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心

    题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...

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

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

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

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

  9. Subsequence(序列自动机模板题)

    题目链接:https://nanti.jisuanke.com/t/38232 题目大意:给你一个字符串,然后再给你m个字符串,然后问你在第一个字符串中不连续的子串能不能构成输入的子串. 具体思路:构 ...

随机推荐

  1. 通过JavaScript原型链理解基于原型的编程

    零.此文动机 用了一段时间的Lua,用惯了Java C++等有Class关键字的语言,一直对Lua的中的面向对象技术感到费解,一个开源的objectlua更是看了n遍也没理解其中的原理,直到看到了Pr ...

  2. 【代码笔记】iOS-点击任何处,显示出红色的UIView

    一,效果图. 二,工程图. 三,代码. RootViewController.h #import <UIKit/UIKit.h> //头文件 #import "MoreView. ...

  3. github邮箱验证技巧

    申请的github账号,绑定邮箱之后才能创建库,而反复几次的发送邮件均为收到验证邮件,猜测有两个原因: 1.腾讯邮件服务器屏蔽了github的来信 (腾讯不会这么狭隘的,×) 2.自己邮箱的域名黑名单 ...

  4. MySQL主主双机负载均衡

    MySQL双机主主架构,其上辅以负载均衡设备,可以实现mysql数据库的负载均衡高性能和高可用性,负载均衡设备可以根据算法将数据库操作的负 载平均分到两台MySQL服务器上,这样对于每台服务器来说工作 ...

  5. 集合迭代器快速失败行为及CopyOnWriteArrayList

    以下内容基于jdk1.7.0_79源码: 什么是集合迭代器快速失败行为 以ArrayList为例,在多线程并发情况下,如果有一个线程在修改ArrayList集合的结构(插入.移除...),而另一个线程 ...

  6. XML语言基础1

    这学期选修了XML技术这门课,没有发课本,于是参考了W3school教程,整理一下上课的内容. 1.XML简介 XML是一种标记语言,很类似HTML,它不是对HTML的替代,而是对HTML的补充.在大 ...

  7. Nginx 简单的负载均衡配置示例(转载)

    原文地址:Nginx 简单的负载均衡配置示例(转载) 作者:水中游于 www.s135.com 和 blog.s135.com 域名均指向 Nginx 所在的服务器IP. 用户访问http://www ...

  8. 深入理解Nginx之调试优化技巧

    在开发过程中,我们经常会碰到段错误等异常,这时我们需要有相应的机制来进行调试,特别是服务提供在线上时,面对大量的日志信息,合理的调试处理机制对于开发来说是一件非常重要的事情,幸好Nginx本身提供了很 ...

  9. js相对路径相关(比如:js中的路径依赖导入该js文件的路径)

    问题描述: 前几天调用同事的js接口文件,在他自己的html测试页面ok,在我这边调用时出现问题. debug过程中,将该测试html移到其他位置都不行,放到原html测试页面同层次路径下是OK的. ...

  10. [Java入门笔记] Java语言简介

    前言 学习Java有一段时间了,但是一直缺少一个系统的思想,现在重新通过书籍中.网上的文章,视频等资料,整理与回顾Java的知识点. 言归正传,让我们先从了解Java语言开始. Java语言的由来 J ...