CF17E Palisection

嘟嘟嘟

题中让求相交的回文串的对数,不太好求。不过求不相交的回文串对数就简单多了。

因为对于一位 i,在这一位不相交的回文串对数numi = 以这一位结束的回文串个数 ×在这一位后面开始的回文串个数。用manacher跑一遍 + 差分,然后维护一个开始的回文串的后缀和就好了。

然后统计回文串个数sum,那么ans = sum * (sum - 1) / 2 - ∑numi

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int mod = 51123987;
21 const int maxn = 2e6 + 5;
22 inline ll read()
23 {
24     ll ans = 0;
25     char ch = getchar(), last = ' ';
26     while(!isdigit(ch)) {last = ch; ch = getchar();}
27     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
28     if(last == '-') ans = -ans;
29     return ans;
30 }
31 inline void write(ll x)
32 {
33     if(x < 0) x = -x, putchar('-');
34     if(x >= 10) write(x / 10);
35     putchar(x % 10 + '0');
36 }
37 
38 int n;
39 char s[maxn], t[maxn << 1];
40 int p[maxn << 1];
41 int enn[maxn << 1], beg[maxn << 1];
42 
43 void init()
44 {
45   t[0] = '@';
46   for(int i = 0; i < n; ++i) t[i << 1 | 1] = '#', t[(i << 1) + 2] = s[i];
47   n = (n << 1) + 2;
48   t[n - 1] = '#'; t[n] = '$';
49 }
50 void manacher()
51 {
52   int mx = 0, id;
53   for(int i = 1; i < n; ++i)
54     {
55       if(mx > i) p[i] = min(p[(id << 1) - i], mx - i);
56       else p[i] = 1;
57       while(t[i - p[i]] == t[i + p[i]]) p[i]++;
58       if(i + p[i] > mx) mx = p[i] + i, id = i;
59     }
60 }
61 
62 ll ans = 0;
63 
64 int main()
65 {
66   n = read();
67   scanf("%s", s);
68   init(); manacher();
69   for(int i = 1; i <= n; ++i)
70     {
71       enn[i - p[i] + 1]++;
72       enn[i + 1]--;
73       beg[i]++;
74       beg[i + p[i]]--;
75       ans = (ans + (p[i] >> 1) % mod) % mod;
76     }
77   ans = (ans * (ans - 1) >> 1) % mod;
78   for(int i = 1, sum = 0; i <= n; ++i)
79     {
80       enn[i] += enn[i - 1]; beg[i] += beg[i - 1];
81       if(i % 2 == 0) ans = (ans - (ll)sum * (ll)enn[i] % mod + mod) % mod, sum = (sum + beg[i]) % mod;
82     }
83   write(ans), enter;
84   return 0;
85 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9773530.html