这个题是我读错某个题的题意,所写出来的求字符串回文子串的数量的代码,正常求回文子串的话都是求通过区间 dp 来求的,但是当 n 比较大的时候是没法的求的,但是我们可以用 Manacher 算法来求出的任意位置(这个位置有两种:1. 奇数长度的回文串的中间位置、2 偶数长度的回文串的中间位置的)的回文子串的长度,然后对每个位置都答案贡献进行统计就行了
代码
#include<bits/stdc++.h>
using namespace std;#definedbdouble#definelllonglong#definePirpair<int,int>#definefifirst#definesesecond#definepbpush_back#definem_pmake_pair#defineinf0x3f3f3f3f#defineINF0x3f3f3f3f3f3f3f3f/*==========ACMer===========*/constint N =2e5+10;int n, m;char a[N <<1], b[N <<1];//存储空间要开 2 倍大小int len[N <<1];voidtrans(){
b[0]='@';for(int i =1; i <=2* n; i +=2){
b[i]='#';
b[i +1]= a[i /2];}
b[2* n +1]='#';
b[2* n +2]='\0';
m =2* n +1;}voidManacher(){int R =0, mid =0;for(int i =1; i <= m; i ++){if(i < R) len[i]=min(R - i, len[2* mid - i]);else len[i]=1;while(b[i - len[i]]== b[i + len[i]]) len[i]++;if(len[i]+ i > R){
R = len[i]+ i;
mid = i;}}}intmain(){scanf("%s", a);
n =strlen(a);trans();Manacher();
cout << b << endl;
ll ans =0;for(int i =0; i < n; i ++){int r1 = len[(i +1)*2]/2;//奇对称, 半径int r2 = len[(i +1)*2+1]/2;//偶对称, 半径
ans += r1;
ans += r2;}printf("%lld\n", ans);//回文串的个数printf("%lld",1LL*(1+ n)* n /2- ans);//区间翻转之后与原串 s 不同的方案数return0;}