其他分享
首页 > 其他分享> > SAM复习

SAM复习

作者:互联网

定义

SAM的定义

字符串\(s\)的SAM是一个可接受\(s\)的所有后缀的最小\(DFA\)(确定的有穷自动机),可以参考编译原理的龙书(强烈推荐)

重要概念

结束为止endpos

考虑SAM中某个不是\(t_0\)的状态\(v\)。状态\(v\)对应于一个等价类,如果定义\(w\)为这个等价类中最长串,那么这个等价类中的其他字符串都是\(w\)的后缀。

并且\(w\)的前几个后缀(按长度降序考虑)全部包含于这个等价类中,且其他后缀在其他等价类中。什么意思,还是用\(s=abcdefgdefgpfg\)这个例子,\(w=defg\),假设\(w\)是它所在\(endpos\)的代表元,那么\(endpos(w)=\{defg,efg\}\),但\(fg,g\)都是\(w\)的后缀,但它们与\(w\)不在同一个等价类中

记\(t\)为不与\(w\)在同一个等价类中但是\(w\)的后缀的最长中的一个,显然\(|t|=minlen-1\)。

于是在状态图中,我们从\(w\)所在的等价类\(v\)向\(t\)所在等价类连一条件记为\(link(v)\),这样的边只有一条

其中蓝色的边是\(SAM\)中有向图的边,虚线的蓝色边为后缀连接\(link\),构成了一棵树

复杂度

构造方法

image

一般可以先求出\(SAM\),然后把\(link\)构成的树重新构建一遍

模板

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e6+10;
struct Node{
    int len,link;
    int ch[26];
}node[N];
int last=1,idx=1;
ll dp[N];
void SAM_Extend(int c){
   int p=last,cur=++idx; //每次新加入的点是一个前缀
   last=cur;
   dp[idx]=1;
   node[cur].len=node[p].len+1;
   for(;p&&!node[p].ch[c];p=node[p].link) node[p].ch[c]=cur;
   if(!p) node[cur].link=1;
   else{
     int q=node[p].ch[c];
     if(node[q].len==node[p].len+1){
        node[cur].link=q;
     }else{
        int nq=++idx;
        node[nq]=node[q];
        node[nq].len=node[p].len+1;
        node[cur].link=node[q].link=nq;
        for(;p&&node[p].ch[c]==q;p=node[p].link) node[p].ch[c]=nq;
     }
   }
}
//构建 link树
struct edges{
    int v,nxt;
}e[N];
int cnt,head[N];
void add(int u,int v){
    e[cnt]={v,head[u]},head[u]=cnt++;
}


//一顿操作
ll ans;
void dfs(int u){
 
    for(int i=head[u];~i;i=e[i].nxt){
        int v=e[i].v;
        dfs(v);
        dp[u]+=dp[v];
    }
    if(dp[u]>1) ans=max(ans,dp[u]*node[u].len);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    memset(head,-1,sizeof head);
    string s;
    cin>>s;
    int n=s.size();
    for(int i=0;i<n;i++) SAM_Extend(s[i]-'a');
    for(int i=2;i<=idx;i++) add(node[i].link,i);
    dfs(1);
    cout<<ans<<'\n';
    return 0;
}

应用

标签:node,子串,复习,SAM,int,后缀,link,endpos
来源: https://www.cnblogs.com/Arashimu0x7f/p/16521494.html