【LG4070】[SDOI2016]生成魔咒
阿新 • • 發佈:2019-03-26
構建 char break oid www. www org tchar ans
【LG4070】[SDOI2016]生成魔咒
題面
洛谷
題解
如果我們不用在線輸的話,那麽答案就是對於所有狀態\(i\)
\[ \sum (i.len-i.fa.len) \]
現在我們需要在線詢問,那麽因為\(SAM\)是在線算法,我們考慮每次的對答案的貢獻。
那麽產生的貢獻就是\(last.len-last.fa.len\)。
與\(yyb\)的對話:
Q:為什麽構建自動機時中間過程新加的點不會算到最後答案中呢?
A:不影響答案啊,你在兩個len之間斷開,對於答案的貢獻不變。
代碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <tr1/unordered_map> using namespace std; using namespace std::tr1; inline int gi() { register int data = 0, w = 1; register char ch = 0; while (!isdigit(ch) && ch != '-') ch = getchar(); if (ch == '-') w = -1, ch = getchar(); while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); return w * data; } const int MAX_N = 1e5 + 5; struct Node { unordered_map<int, int> ch; int len, fa; } t[MAX_N << 1]; int tot = 1, lst = 1; long long ans = 0; void extend(int c) { int New = ++tot; t[lst].ch[c] = New; t[New].len = t[lst].len + 1; int p = t[lst].fa; lst = tot; while (p && t[p].ch.find(c) == t[p].ch.end()) t[p].ch[c] = New, p = t[p].fa; if (!p) t[New].fa = 1; else { int q = t[p].ch[c]; if (t[q].len == t[p].len + 1) t[New].fa = q; else { int _q = ++tot; t[_q] = t[q]; t[New].fa = t[q].fa = _q, t[_q].len = t[p].len + 1; while (p) { unordered_map<int, int> :: iterator ite; ite = t[p].ch.find(c); if (ite == t[p].ch.end() || ite->second != q) break; t[p].ch[c] = _q; p = t[p].fa; } } } ans += t[New].len - t[t[New].fa].len; } int main () { #ifndef ONLINE_JUDGE freopen("cpp.in", "r", stdin); #endif int N = gi(); for (int i = 1; i <= N; i++) extend(gi()), printf("%lld\n", ans); return 0; }
【LG4070】[SDOI2016]生成魔咒