【数据结构】广义 SAM 简述
广义后缀自动机简述
不了解后缀自动机的可以看看:
https://www.cnblogs.com/Tenshi/p/16408718.html
在字典树的基础上建立广义后缀自动机。
建立
对若干模式串,先插入字典树中。
注意到对字典树进行 的时候,对应的状态的 是不降的(状态和 的概念参考后缀自动机)。
所以我们按照这个顺序将字符一次插入到后缀自动机中,并相应地建立 。
而插入的过程可以按照普通的 SAM 的插入操作修改而来。
模板题以及代码实现
https://www.luogu.com.cn/problem/P6139
// Problem: P6139 【模板】广义后缀自动机(广义 SAM)
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P6139
// Memory Limit: 500 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define x first
#define y second
using pii = pair<int, int>;
using ll = long long;
inline void read(int &x){
int s=0; x=1;
char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
x*=s;
}
const int N=2e6+5, CHR=26;
int n;
struct GSAM{
struct Node{
int fa, len;
int ch[CHR];
}node[N];
int tot;
void init(){
tot=1;
node[tot].fa=0;
}
void insert(string &s){
int u=1;
for(auto &i: s){
int &go=node[u].ch[i-'a'];
if(!go) go=++tot;
u=go;
}
}
int ins(int last, int c){
int cur=node[last].ch[c];
if(node[cur].len) return cur;
node[cur].len=node[last].len+1;
int p=node[last].fa;
for(; p && !node[p].ch[c]; p=node[p].fa) node[p].ch[c]=cur;
if(!p) return node[cur].fa=1, cur;
int q=node[p].ch[c];
if(node[p].len+1==node[q].len) return node[cur].fa=q, cur;
int nq=++tot;
rep(i,0,CHR-1) node[nq].ch[i]=(node[node[q].ch[i]].len==0? 0: node[q].ch[i]);
node[nq].len=node[p].len+1;
for(; p && node[p].ch[c]==q; ) node[p].ch[c]=nq, p=node[p].fa;
node[nq].fa=node[q].fa;
node[cur].fa=node[q].fa=nq;
return cur;
}
void build(){
queue<pii> q;
rep(i,0,CHR-1) if(node[1].ch[i]) q.push({1, i});
while(q.size()){
auto [x, y]=q.front(); q.pop();
int last=ins(x, y);
rep(i,0,CHR-1) if(node[last].ch[i]) q.push({last, i});
}
}
void solve(){
ll res=0;
rep(i,2,tot) res+=node[i].len-node[node[i].fa].len;
cout<<res<<endl;
}
}gsam;
int main(){
cin>>n;
gsam.init();
rep(i,1,n){
string s; cin>>s;
gsam.insert(s);
}
gsam.build();
gsam.solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】