题解 P5826 【【模板】子序列自动机】
y2823774827y · · 题解
更好的阅读体验
序列自动机
- 构造
for(LL i=n;i>=1;--i){
for(LL j=1;j<=a;++j) nxt[i-1][j]=nxt[i][j];
nxt[i-1][s[i]]=i;
}
- 扩展构建
当字符集较大时,可套用可持久化,在叶子节点放一个
相关例题:
字符串
一步一步(从首到尾)走,有序确定code
经典例题
- 判断是否是原字符串的子序列
构造出了
- 求子序列个数
从根跑,记忆化搜索,
- 求两串的公共子序列个数
两串都构造一下,之间跑就好了。
LL Dfs(LL x,LL y){
if(f[x][y]) return f[x][y];
for(LL i=1;i<=a;++i)
if(nxt1[x][i]&&nxt2[y][i])
f[x][y]+=Dfs(nxt1[x][i],nxt2[y][i]);
return ++f[x][y];
}
- 求字符串的回文子序列个数
原串与反串都建一遍
就相当于从左右端点这样跑。
求的时候显然
LL Dfs(LL x,LL y){
if(f[x][y]) return f[x][y];
for(LL i=1;i<=a;++i)
if(nxt1[x][i]&&nxt2[y][i]){
if(nxt1[x][i]+nxt2[y][i]>n+1) continue;
if(nxt1[x][i]+nxt2[y][i]<n+1) f[x][y]++;
f[x][y]=(f[x][y]+Dfs(nxt1[x][i],nxt2[y][i]))%mod;
}
return ++f[x][y];
}
- 求一个
A,B 的最长公共子序列S ,使得C 是S 的子序列
还是同样的
改变一下
for(LL i=1;i<=a;++i) nxt[n][i]=n;
for(LL i=0;i<n;++i){
for(LL j=1;j<=a;++j) nxt[i][j]=i;
nxt[i][c[i+1]]=i+1;
}