3160: 万径人踪灭
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 814 Solved: 459
[ Submit][ Status][ Discuss]
Description
Input
Output
Sample Input
Sample Output
HINT
Source
吐槽:我替“千山鸟飞绝”感到不服。
manacher+FFT,思路好题
补集思想,直接求不连续的有点难,我们可以求出所有回文串,然后减去其中连续的。
连续回文串很好求,manacher就可以解决。
问题在于如何求不一定连续的回文串,如果求出以每个位置i为对称中心,对称的字符对的个数f[i],那对于答案的贡献就加上2^f[i]-1,证明很显然。
于是问题又成了如何求f[i]。
发现字符串中只有两种字符,而且对称的点的下标和为定值。于是我们可以先令a=1、b=0,再令a=0、b=1,分别用FFT求出卷积,就可以得到相等且下标和为x的字符对数。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 300005
#define mod 1000000007
using namespace std;
int n,len,ans,rev[maxn],f[maxn],bin[maxn];
char s[maxn],st[maxn];
const double pi=acos(-1.0);
struct cp
{
double x,y;
cp(double xx=0,double yy=0){x=xx;y=yy;}
friend cp operator +(cp a,cp b){return cp(a.x+b.x,a.y+b.y);}
friend cp operator -(cp a,cp b){return cp(a.x-b.x,a.y-b.y);}
friend cp operator *(cp a,cp b){return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
}a[maxn],b[maxn];
void fft(cp *x,int n,int flag)
{
F(i,0,n-1) if (rev[i]>i) swap(x[i],x[rev[i]]);
for(int m=2;m<=n;m<<=1)
{
int mid=m>>1;
cp wn(cos(2.0*pi/m*flag),sin(2.0*pi/m*flag));
for(int i=0;i<n;i+=m)
{
cp w(1.0,0);
F(j,0,mid-1)
{
cp u=x[i+j],v=x[i+j+mid]*w;
x[i+j]=u+v;x[i+j+mid]=u-v;
w=w*wn;
}
}
}
if (flag==-1) F(i,0,n-1) x[i].x/=n;
}
void manacher()
{
int mx=0,id=0;
F(i,1,n)
{
if (mx>i) f[i]=min(mx-i,f[id*2-i]);
else f[i]=0;
while (s[i+f[i]]==s[i-f[i]]) f[i]++;
if (i+f[i]>mx) mx=i+f[i],id=i;
ans=(ans-f[i]/2+mod)%mod;
}
}
int main()
{
bin[0]=1;F(i,1,100000) bin[i]=bin[i-1]*2%mod;
scanf("%s",s+1);
len=strlen(s+1);
n=1;int tmp=0;
while (n<len*2) n<<=1,tmp++;
F(i,1,n-1){rev[i]=rev[i>>1]>>1|((i&1)<<(tmp-1));}
F(i,0,len-1) if (s[i+1]=='a') a[i].x=1;
fft(a,n,1);
F(i,0,n-1) a[i]=a[i]*a[i];
fft(a,n,-1);
F(i,0,len-1) if (s[i+1]=='b') b[i].x=1;
fft(b,n,1);
F(i,0,n-1) b[i]=b[i]*b[i];
fft(b,n,-1);
F(i,0,n-1)
{
int x=round(a[i].x+b[i].x);
x=(x+1)/2;
ans=(ans+bin[x]-1)%mod;
}
F(i,1,len) st[i]=s[i];
n=len<<1|1;
s[0]='*';s[1]='#';s[n+1]='&';
F(i,1,len) s[i<<1]=st[i],s[i<<1|1]='#';
manacher();
printf("%d\n",ans);
return 0;
}