最近学习了一下后缀自动机,但还是有点懵懵懂懂,这里先把我能看懂的博客贴出来,以便以后学习。然后以后有了自己的感悟,再来补充。
1.后缀自动机详解
模板:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <string> #include <map> #include <queue> using namespace std; typedef long long llt; const int N = 1000010; struct state{ int len,link,cnt; map<char,int>next; }st[N*2]; int sz,last,ans[N],inDeg[N*2]; void sa_init() { sz = last = 0; st[0].len = 0; st[0].link = -1; ++sz; for(int i = 0; i < N; ++i) st[i].next.clear(),st[i].cnt = 0; memset(ans,0,sizeof(ans)); memset(inDeg,0,sizeof(inDeg)); } void sa_extend(char c) { int cur = sz++; //新添加的状态结点 st[cur].len = st[last].len+1; st[cur].cnt = 1; int p; for(p = last; p != -1 && !st[p].next.count(c); p = st[p].link) st[p].next[c] = cur; if(p == -1) st[cur].link = 0; else{ int q = st[p].next[c]; if(st[p].len+1 == st[q].len) st[cur].link = q,inDeg[q]++; else{ int clone = sz++; st[clone].len = st[p].len+1; st[clone].next = st[q].next; st[clone].link = st[q].link; for(; p != -1 && st[p].next[c] == q; p = st[p].link) st[p].next[c] = clone; st[q].link = st[cur].link = clone; inDeg[clone] += 2; } } last = cur; } void bfs() { queue<int>q; for(int i = 1; i < sz; ++i) if(!inDeg[i]) q.push(i); while(!q.empty()){ int u = q.front(); q.pop(); int v = st[u].link; ans[st[u].len] = max(ans[st[u].len],st[u].cnt); st[v].cnt += st[u].cnt; inDeg[v]--; if(!inDeg[v]) q.push(v); } } int main() { sa_init(); string str; cin >> str; for(int i = 0; i < str.length(); ++i) sa_extend(str[i]); return 0; }
简单习题: