参考了 (Miracle) 的博客
因为要做最短不公共xx的那个题所以来学了子序列自动机
其实这个就像一个 主席树,前一个继承这个的状态然后修改一个位置
然后和 (SAM) 一样,如果从 (0) 开始 (dfs) ,每到一个点的路径都是一个子序列
别的好像没啥用,都是就题论题
Code
for(reg short i=n,pos;i>=1;--i){
for(reg short j=1;j<=52;++j) n1[i-1][j]=n1[i][j];
if(s1[i]>='a') pos=s1[i]-'a'+27;
else pos=s1[i]-'A'+1;
n1[i-1][pos]=i;
}
for(reg short i=m,pos;i>=1;--i){
for(reg short j=1;j<=52;++j) n2[i-1][j]=n2[i][j];
if(s2[i]>='a') pos=s2[i]-'a'+27;
else pos=s2[i]-'A'+1;
n2[i-1][pos]=i;
}
例题
FJOI2016所有公共子序列问题
直接套上去然后 (dp) 就行了,需要压位高精
这里和普通高精的不同是 (bas) 不要设成 (1e9+10) 这样子,同时先输出最高位
,像这样:
inline void print(){
cout<<a[len];
for(reg int i=len-1;i>=1;--i) printf("%09d",a[i]); puts("");
return ;
}
或者按照 (LCIS) 的 (O(n^2)) 做法
设 (f[i][j]) 表示 (i) 不必选,(j) 必选的方案数
如果 (a[i]=b[j]) ,(f[i][j]=1+sumlimits_{id} f_{i-1,bnxt[j][id]})
反之就是 (f[i][j]=f[i-1][j])
HEOI2015最短不公共子串
建出来 (SAM) 和 子序列自动机之后就俩一起跑就行了
这题教我如何写广搜,那么记录一下写挂的几个点:
((1)) 广搜要记录 (vis) ,而且是在入队之前记录
((2)) (SAM) 的状态数最大是 (2n-1) ,证明显然,构造是 (abbbb...bbbb)
同时“转移数”不会超过 (3n-4)