Panlindromic Tree(迴文樹)的四個例題

http://www.tsinsen.com/new/A1280 html

雙迴文串,正着作一遍,倒着作一遍,維護每一個節點 向前向後的最長迴文子串長度(len[ last ])node

 1 #include <bits/stdc++.h>
 2 const long long mod = 1e9+7;
 3 const double ex = 1e-10;
 4 #define inf 0x3f3f3f3f
 5 using namespace std;
 6 const int MAXN = 212345;
 7 const int N = 26;
 8 struct Palindromic_Tree{
 9     int next[MAXN][N];
10     int fail[MAXN];
11     int cnt[MAXN];
12     int num[MAXN];
13     int len[MAXN];
14     int S[MAXN];
15     int last;
16     int n;
17     int p;
18     int newnode(int l){
19         for (int i = 0 ; i<N; i++) next[p][i] = 0;
20         cnt[p] = 0;
21         num[p] = 0;
22         len[p] = l;
23         return p++;
24     }
25     void init(){
26         p = 0;
27         newnode(0);
28         newnode(-1);
29         last = 0;
30         n  = 0;
31         S[n] = -1;
32         fail[0] = 1;
33     }
34     int get_fail(int x){
35         while (S[n-len[x]-1] != S[n]) x = fail[x];
36         return x;
37     }
38     int add(int c){
39         c-='a';
40         S[++n] = c;
41         int cur = get_fail(last);
42         if (!next[cur][c]){
43             int now = newnode(len[cur] + 2);
44             fail[now] = next[get_fail(fail[cur])][c];
45             next[cur][c] = now;
46             num[now] = num[fail[now]] + 1;
47         }
48         last = next[cur][c];
49         cnt[last]++;
50         return len[last];
51     }
52     void count(){
53         for (int i = p-1  ; i >= 0; i--) cnt[fail[i]] += cnt[i];
54     }
55 };
56 Palindromic_Tree a;
57 int len[212345];
58 int main()
59 {
60     string s;
61     cin >> s;
62     int l = s.length();
63     a.init();
64     for (int i = 0 ; i<l ; i++){
65         len[i] = a.add(s[i]);
66     }
67     a.init();
68     int ans = 0;
69     for (int i = l-1; i>=1 ;i--){
70         ans = max(ans , len[i-1] + a.add(s[i]));
71     }
72     cout << ans << endl;
73     return 0;
74 }
View Code

http://www.tsinsen.com/new/A1255ios

能夠把每種串的 數目和長度存下來,按照長度排個序,從大到小維護。c++

 1 #include <bits/stdc++.h>
 2 const long long mod = 19930726;
 3 const double ex = 1e-10;
 4 #define inf 0x3f3f3f3f
 5 using namespace std;
 6 const int MAXN = 2123456;
 7 const int N = 26;
 8 struct Palindromic_Tree{
 9     int next[MAXN][N];
10     int fail[MAXN];
11     int cnt[MAXN];
12     int num[MAXN];
13     int len[MAXN];
14     int S[MAXN];
15     int last;
16     int n;
17     int p;
18     int newnode(int l){
19         for (int i = 0 ; i<N; i++) next[p][i] = 0;
20         cnt[p] = 0;
21         num[p] = 0;
22         len[p] = l;
23         return p++;
24     }
25     void init(){
26         p = 0;
27         newnode(0);
28         newnode(-1);
29         last = 0;
30         n  = 0;
31         S[n] = -1;
32         fail[0] = 1;
33     }
34     int get_fail(int x){
35         while (S[n-len[x]-1] != S[n]) x = fail[x];
36         return x;
37     }
38     void add(int c){
39         c-='a';
40         S[++n] = c;
41         int cur = get_fail(last);
42         if (!next[cur][c]){
43             int now = newnode(len[cur] + 2);
44             fail[now] = next[get_fail(fail[cur])][c];
45             next[cur][c] = now;
46             num[now] = num[fail[now]] + 1;
47         }
48         last = next[cur][c];
49         cnt[last]++;
50     }
51     void count(){
52         for (int i = p-1  ; i >= 0; i--) cnt[fail[i]] += cnt[i];
53     }
54 };
55 Palindromic_Tree a;
56 int len[212345];
57 typedef pair<int,long long> pii;
58 pii p[1000022];
59 long long ksm(long long x,long long y){
60     long long ans = 1;
61     while (y){
62         if (y % 2) ans = ans * x % mod;
63         x = x*x % mod;
64         y/=2;
65     }
66     return ans;
67 }
68 int main()
69 {
70     string s;
71     int l;
72     long long k;
73     cin >> l >> k;
74     cin >> s;
75     a.init();
76     for (int i = 0 ; i<l ; i++){
77         a.add(s[i]);
78     }
79     a.count();
80     int cnt = 0;
81     for (int i = 2 ; i<a.p ; i++){
82         if (a.len[i] % 2 == 0) continue;
83         p[cnt++] = make_pair(a.len[i],(long long)a.cnt[i]);
84     }
85     sort(p,p+cnt);
86     long long ans = 1;
87     int i = cnt-1;
88     while (k > 0 && i >= 0){
89         ans = (ans * ksm((long long)p[i].first,min(p[i].second,k))) % mod;
90         k -= min(k,p[i].second);
91         i--;
92     }
93     if (k > 0){
94         puts("-1");
95     }
96     else cout << ans << endl;
97 }
View Code

http://www.tsinsen.com/new/A1393數組

這個題仍是CF的17E,貌似迴文樹不是正解,可能須要馬拉車優雅的過,明天學學馬拉車寫了他吧。ide

這個題,第一次理解了num的含義,num記錄的是每一類迴文串的①性質不一樣,②結尾相同(左對齊)的子串數目。學習

其中限制條件 性質不一樣  能夠有多種理解,他們 長度 不一樣 且 左對齊,顯然他們性質不一樣spa

另外還有,以某個節點爲 右端點的全部迴文子串 確定 性質不一樣。code

讓求相交的迴文串對數 , 能夠 反着求,求出總的對數,減去不相交的便可。htm

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <string>
 4 #include <algorithm>
 5 #include <iostream>
 6 const long long mod = 51123987;
 7 const double ex = 1e-10;
 8 #define inf 0x3f3f3f3f
 9 using namespace std;
10 const int MAXN = 2000009;
11 const int N = 26;
12 struct Palindromic_Tree{
13     int next[MAXN][N];
14     int fail[MAXN];
15     int cnt[MAXN];
16     int num[MAXN];
17     int len[MAXN];
18     short S[MAXN];
19     int last;
20     int n;
21     int p;
22     int newnode(int l){
23         for (int i = 0 ; i<N; i++) next[p][i] = 0;
24         cnt[p] = 0;
25         num[p] = 0;
26         len[p] = l;
27         return p++;
28     }
29     void init(){
30         p = 0;
31         newnode(0);
32         newnode(-1);
33         last = 0;
34         n  = 0;
35         S[n] = -1;
36         fail[0] = 1;
37     }
38     int get_fail(int x){
39         while (S[n-len[x]-1] != S[n]) x = fail[x];
40         return x;
41     }
42     int add(int c){
43         c-='a';
44         S[++n] = c;
45         int cur = get_fail(last);
46         if (!next[cur][c]){
47             int now = newnode(len[cur] + 2);
48             fail[now] = next[get_fail(fail[cur])][c];
49             next[cur][c] = now;
50             num[now] = num[fail[now]] + 1;
51         }
52         last = next[cur][c];
53         cnt[last]++;
54         return num[last];
55     }
56     long long count(){
57         for (int i = p-1  ; i >= 0; i--) cnt[fail[i]] += cnt[i];
58         long long ans = 0;
59         for (int i = 2 ; i<p;i++)
60             ans = (ans + cnt[i])% mod;
61         return ans;
62     }
63 };
64 Palindromic_Tree a;
65 int sum[2000009];
66 int main()
67 {
68     string s;
69     int l;
70     cin >> l;
71     cin >> s;
72     a.init();
73     for (int i = 0 ; i<l ; i++){
74         sum[i] = a.add(s[i]);
75     }
76     for (int i = 1 ; i<l ;i++){
77         sum[i] = (sum[i] + sum[i-1]) % mod;
78     }
79     long long ans = a.count();
80     ans = ans * (ans - 1 ) / 2 % mod;
81     a.init();
82     for (int i = l-1; i>0 ; i--){
83         long long x = a.add(s[i]);
84         ans = ((ans - x * sum[i-1]) % mod + mod) % mod;
85     }
86     cout << ans << endl;
87     return 0;
88 }
View Code

卡內存卡到死,CF根本過不去,tsinsen也是卡過的。

不過這個題讓我深入理解了num數組的含義

還有一題以前寫過的

http://www.cnblogs.com/HITLJR/p/7687885.html

學習迴文樹,首先把代碼看懂,找幾個簡單的本身模擬一下整個過程,而後理解每一個數組的含義,靈活運用add的返回值求一些東西。

相關文章
相關標籤/搜索