「学习笔记」子序列自动机

参考了 (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)

原文地址:https://www.cnblogs.com/yspm/p/14177782.html