回文子串的个数
给定一个字符串,求字符串中有多少个回文子串
单独一个字符也是一个回文串
# 题解
manacher,从1开始扫描整个回文半径数组,以每个点为中心的
回文串的个数为 hw[i]/2,即除去分隔符的真实回文半径
#1#2#3#3#2#1#
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=200010; 4 char a[maxn],s[maxn<<1]; 5 int l[maxn<<1],r[maxn<<1]; 6 int n,hw[maxn],ans; 7 // hw/2 即以 i 为中心的回文子串的个数 8 // hw[ i ]-1即以 i 为中心的回文串的长度 9 //在所有字符的前后 共插入n+1 个 '#' 10 inline void change() { 11 s[0]='~',s[1]='#';//边界 12 for(int i=0; i<n; i++) { 13 s[i*2+2]=a[i]; 14 s[i*2+3]='#'; 15 } 16 n=n*2+2; 17 s[n]='@';// 设置边界,两个边界不同 18 } 19 inline void manacher( ) { 20 int maxright=0 , mid; 21 for(int i = 1; i < n; i ++) {//枚举1...2n-1 22 if(i < maxright) 23 hw[i] = min ( hw[(mid << 1) - i ] , hw [mid] + mid - i ); 24 // hw[(mid<<1)-i]即i关于mid对称的点. hw[mid] +mid-i,为当前到最长回文串终点的距离,特判定对称的点越界 25 else 26 hw[i] = 1;//hw[i]表示i点能够扩展出的回文半径 27 while( s[i + hw[i]] == s[i - hw[i]] )//s[]存储字符串 28 ++ hw[i]; 29 if(hw[i] + i > maxright) { 30 maxright = hw[i] + i - 1; 31 mid = i; 32 } 33 } 34 } 35 int main(){ 36 cin>>a; 37 n=strlen(a); 38 change(); 39 manacher(); 40 int ans=0; 41 for(int i=0;i<n;i++) 42 ans+=hw[i]/2; 43 cout<<ans; 44 }