洛谷P4070 生成魔咒

題意:給定字符串,求每一個前綴的本質不一樣的子串數量。字符集1e9。ide

解:在線構造後綴自動機並統計答案。spa

答案就是∑len[i] - len[fail[i]]code

每次增長的時候,至多對三個節點有影響。然而把Q分裂爲nQ本質不一樣的子串數沒變。blog

因而增長的只有len[np] - len[fail[np]]字符串

map維護轉移邊。it

 1 #include <cstdio>
 2 #include <map>
 3 
 4 typedef long long LL;
 5 const int N = 200010;
 6 
 7 int len[N], fail[N], last, top;
 8 LL ans;
 9 std::map<int, int> mp[N];
10 
11 inline void init() {
12     top = last = 1;
13     return;
14 }
15 
16 inline void insert(int f) {
17     int p = last, np = ++top;
18     last = np;
19     len[np] = len[p] + 1;
20     while(p && !mp[p].count(f)) {
21         mp[p][f] = np;
22         p = fail[p];
23     }
24     //printf("p = %d \n", p);
25     if(!p) {
26         fail[np] = 1;
27         ans += len[np];
28         //printf("1 : ans += %d \n", len[np]);
29     }
30     else {
31         int Q = mp[p][f];
32         //printf("Q = %d \n", Q);
33         if(len[Q] == len[p] + 1) {
34             fail[np] = Q;
35             ans += len[np] - len[Q];
36             //printf("2 : ans += %d \n", len[np] - len[Q]);
37         }
38         else {
39             int nQ = ++top;
40             len[nQ] = len[p] + 1;
41             fail[nQ] = fail[Q];
42             fail[Q] = fail[np] = nQ;
43             mp[nQ] = mp[Q];
44             while(mp[p].count(f) && mp[p][f] == Q) {
45                 mp[p][f] = nQ;
46                 p = fail[p];
47             }
48             ans += len[np] - len[nQ];
49         }
50     }
51     return;
52 }
53 
54 int main() {
55     int n;
56     scanf("%d", &n);
57     init();
58     for(int i = 1, x; i <= n; i++) {
59         scanf("%d", &x);
60         insert(x);
61         printf("%lld\n", ans);
62     }
63 
64     return 0;
65 }
AC代碼
相關文章
相關標籤/搜索