最近学习了一下后缀自动机,但还是有点懵懵懂懂,这里先把我能看懂的博客贴出来,以便以后学习。然后以后有了自己的感悟,再来补充。
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;
}
简单习题: