后缀自动机构建后缀数组
@(XSY)[后缀自动机, 后缀数组, 后缀树]
事实上构建后缀数组完全没有必要这么麻烦...
但作为对后缀自动机/后缀树的初步熟悉, 写一写还是很有必要的...
明明是线性构造, 为什么跑得比\(O(n \log n)\)倍增的还要慢...
#include <cstdio>
#include <cstring>
const int LEN = (int)5e4;
char str[LEN];
struct suffixTree
{
int rk[LEN], SA[LEN], ht[LEN];
struct node
{
int suc[26], pos, isRl;
inline node()
{
memset(suc, -1, sizeof(suc));
}
}nd[LEN << 1];
inline void addEdge(int u, int v, int c)
{
nd[u].suc[c] = v;
}
int cnt;
inline void DFS(int u)
{
if(nd[u].isRl)
rk[nd[u].pos] = cnt, SA[cnt ++] = nd[u].pos;
for(int i = 0; i < 26; ++ i)
if(~ nd[u].suc[i])
DFS(nd[u].suc[i]);
}
inline void getAnswer()
{
cnt = 0;
DFS(0);
for(int i = 0; i < cnt; ++ i)
printf("%d ", rk[i] + 1);
puts("");
ht[0] = 0;
int p = 0;
for(int i = 0; i < cnt; ++ i)
if(rk[i])
{
for(p ? -- p : p ; i + p < cnt && SA[rk[i] - 1] + p < cnt && str[i + p] == str[SA[rk[i] - 1] + p]; ++ p);
ht[rk[i]] = p;
}
for(int i = 0; i < cnt; ++ i)
printf("%d ", ht[i]);
}
}tr;
struct suffixAutomaton
{
int s, lst, tp;
struct state
{
int suc[26], pre, dis, pos, isRl;
inline state()
{
memset(suc, -1, sizeof(suc));
pre = pos = -1, dis = isRl = 0;
}
}nd[LEN << 1];
inline void initialize()
{
s = lst = 0;
tp = 1;
}
inline void insert(int c, int pos)
{
int pre = lst, u = tp ++;
nd[u].pos = pos, nd[u].dis = nd[pre].dis + 1, nd[u].isRl = 1;
for(; ~ pre && nd[pre].suc[c] == -1; pre = nd[pre].pre)
nd[pre].suc[c] = u;
if(pre == -1)
nd[u].pre = s;
else
{
int preSuc = nd[pre].suc[c];
if(nd[preSuc].dis == nd[pre].dis + 1)
nd[u].pre = preSuc;
else
{
int v = tp ++;
nd[v] = nd[preSuc];
nd[v].dis = nd[pre].dis + 1, nd[v].isRl = 0;
nd[preSuc].pre = nd[u].pre = v;
for(; ~ pre && nd[pre].suc[c] == preSuc; pre = nd[pre].pre)
nd[pre].suc[c] = v;
}
}
lst = u;
}
inline void buildSuffixTree(char *str)
{
for(int i = 0; i < tp; ++ i)
tr.nd[i].isRl = nd[i].isRl, tr.nd[i].pos = nd[i].pos;
for(int i = 0; i < tp; ++ i)
if(~ nd[i].pre)
tr.addEdge(nd[i].pre, i, (int)str[nd[i].pos + nd[nd[i].pre].dis] - 'a');
}
}SAM;
int main()
{
#ifndef ONLINE_JUDGE
freopen("suffixSort.in", "r", stdin);
freopen("suffixSort.out", "w", stdout);
#endif
gets(str);
int len = strlen(str);
SAM.initialize();
for(int i = len - 1; ~ i; -- i)
SAM.insert((int)str[i] - 'a', i);
SAM.buildSuffixTree(str);
tr.getAnswer();
}