給定一個字符串,求字符串中有多少個回文子串
單獨一個字符也是一個回文串
# 題解
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 }