回文子串的个数

# 题意

给定一个字符串,求字符串中有多少个回文子串
单独一个字符也是一个回文串

# 题解
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 }

 

 

 

 

 

posted @ 2020-03-20 00:53  Hyx'  阅读(1047)  评论(0编辑  收藏  举报