后缀树简短实现
也没什么好讲的,背下来也没什么问题。
不过理解更好吧。
对应洛谷后缀自动机的模板题
。。。。。。。。。。。。。
虽然后缀树很强,但是请注意:
常数还是有的(而且比较大。。。。,估计是唯一不如后缀自动机的地方)
节点数很难超过1.5*n,考场上可以试试卡卡空间什么的
#include <cstdio> #include <cstring> #define sid 2000500 #define inf 100000000 #define ri register int #define ll long long using namespace std; template <typename re> inline void upmax(re &a, re b) { if(a < b) a = b; } char s[1000050]; struct P { int lef, len, link; int go[27]; } t[sid]; int cnt = 1, act = 1, rem, n; ll ans; int node(int l, int len) { t[++ cnt].lef = l; t[cnt].len = len; t[cnt].link = 1; return cnt; } void attend(int i) { n ++; s[i] = s[i] - 'a'; int x = s[i], lst = 1; rem ++; while(rem) { while(rem > t[t[act].go[s[n - rem + 1]]].len) rem -= t[act = t[act].go[s[n - rem + 1]]].len; int tar = s[n - rem + 1], &d = t[act].go[tar]; int c = s[t[d].lef + rem - 1]; if(!d || x == c) { t[lst].link = act; lst = act; if(!d) d = node(n - rem + 1, inf); else return; } else { int np = node(t[d].lef, rem - 1); t[np].go[x] = node(n, inf); t[np].go[c] = d; t[d].lef += rem - 1; t[d].len -= rem - 1; t[lst].link = d = np; lst = d; } (act == 1) ? rem -- : act = t[act].link; } } int has[sid]; void dfs(int e, int dep) { int p = 0; if(dep > n) has[e] ++; for(int i = 0; i <= 26; i ++) { int d = t[e].go[i]; if(!d) continue; dfs(d, dep + t[d].len); has[e] += has[d]; } if(has[e] >= 2) upmax(ans, 1ll * has[e] * dep); } int main() { scanf("%s", s + 1); int n = strlen(s + 1); s[++ n] = 'z' + 1; t[0].len = inf; for(ri i = 1; i <= n; i ++) attend(s[i]); dfs(1, 0); printf("%lld\n", ans); return 0; }
喵喵喵?喵喵喵! 喵喵喵......