啊……Manacher修改一下就好啦~蛮水的……

  Manacher原本是找首尾相同的子串,即回文串,我们这里是要找对应位置不同的“反回文串”(反对称?233)

  长度为奇数的肯定不满足>_>(中间那个字符无论如何不反对称)

  那么我们就找'#'为中心的即可……

  将判断条件a[i-p[i]-1]==a[i+p[i]+1]改成【不等……或是两个都是'#'】

  将所有的p[i]加起来,即所有“反回文串”的长度加起来除以二就是答案啦~

  看代码吧>_<

 1 /**************************************************************
 2     Problem: 2084
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:68 ms
 7     Memory:9572 kb
 8 ****************************************************************/
 9  
10 //BZOJ 2084
11 #include<vector>
12 #include<cstdio>
13 #include<cstring>
14 #include<cstdlib>
15 #include<iostream>
16 #include<algorithm>
17 #define rep(i,n) for(int i=0;i<n;++i)
18 #define F(i,j,n) for(int i=j;i<=n;++i)
19 #define D(i,j,n) for(int i=j;i>=n;--i)
20 #define pb push_back
21 using namespace std;
22 typedef long long LL;
23 inline int getint(){
24     int r=1,v=0; char ch=getchar();
25     for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1;
26     for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0';
27     return r*v;
28 }
29 const int N=5e5+10,INF=~0u>>2;
30 /*******************template********************/
31 char s[N];
32 int a[N<<1],p[N<<1];
33 int main(){
34     int n=getint();
35     scanf("%s",s);
36     F(i,1,n) a[i<<1]=s[i-1];
37     n=n<<1|1;
38     int id=0,ans=0;
39     F(i,1,n){
40         if (a[i]!=0) continue;
41         if (p[id]+id>i) p[i]=min(p[2*id-i],p[id]+id-i);
42         else p[i]=0;
43         while(i-p[i]-1>0 && i+p[i]+1<=n &&
44             (a[i-p[i]-1]!=a[i+p[i]+1] || a[i-p[i]-1]==0))p[i]++;
45         if (p[i]+i>p[id]+id) id=i;
46         ans+=p[i];
47     }
48     printf("%d\n",ans/2);
49     return 0;
50 }
View Code

相关文章: