题中让求相交的回文串的对数,不太好求。不过求不相交的回文串对数就简单多了。
因为对于一位 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 }