Solution

$ans=$回文子序列$-$回文子串的数目。

后者可以用$manacher$直接求。

前者设$f[i]$表示以$i$为中心的对称的字母对数。

那么回文子序列的数量也就是$\sum_{i=0}^{n-1}2^{f[i]-1}$

构造两个数组$a[i],b[i]$。若第$i$位为$a$,那么$a[i]=1$,否则$b[i]=1$。

可以发现$a$数组自身卷积就是$a$字母对$f$数组的贡献,$b$数组同理。

卷下$a$,卷下$b$,对应位置求和,就是$f$数组。

因为在卷积中每对对称字符被算了两次,而自己和自己关于自己对称只算了一次,所以要把答案除2向上取整。

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define N (400009)
#define LL long long
#define MOD (1000000007)
using namespace std; int n,fn,l,tot,r[N],len[N],p[N];
LL Re,fun;
char s[N],st[N];
double pi=acos(-1.0);
struct complex
{
double x,y;
complex (double xx=,double yy=)
{
x=xx; y=yy;
}
}a[N],b[N]; complex operator + (complex a,complex b) {return complex(a.x+b.x,a.y+b.y);}
complex operator - (complex a,complex b) {return complex(a.x-b.x,a.y-b.y);}
complex operator * (complex a,complex b) {return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
complex operator / (complex a,double b) {return complex(a.x/b,a.y/b);} void FFT(int n,complex *a,int opt)
{
for (int i=; i<n; ++i)
if (i<r[i]) swap(a[i],a[r[i]]);
for (int k=; k<n; k<<=)
{
complex wn=complex(cos(pi/k),opt*sin(pi/k));
for (int i=; i<n; i+=k<<)
{
complex w=complex(,);
for (int j=; j<k; ++j,w=w*wn)
{
complex x=a[i+j], y=w*a[i+j+k];
a[i+j]=x+y; a[i+j+k]=x-y;
}
}
}
if (opt==-) for (int i=; i<n; ++i) a[i]=a[i]/n;
} void Manacher()
{
s[++tot]='('; s[++tot]='#';
for (int i=; i<n; ++i)
s[++tot]=st[i], s[++tot]='#';
s[++tot]=')';
int maxn=,mid=,x;
for (int i=; i<=tot; ++i)
{
if (i>maxn) x=;
else x=min(maxn-i+,len[mid*-i]);
while (s[i+x]==s[i-x]) x++;
len[i]=x;
if (i+x->maxn) maxn=i+x-, mid=i;
fun=(fun+len[i]/)%MOD;
}
} int main()
{
p[]=;
for (int i=; i<=; ++i)
p[i]=p[i-]*%MOD;
scanf("%s",st); n=strlen(st);
Manacher(); fn=;
while (fn<=n+n) fn<<=, l++;
for (int i=; i<fn; ++i)
r[i]=(r[i>>]>>) | ((i&)<<(l-));
for (int i=; i<n; ++i)
if (st[i]=='a') a[i].x=;
else b[i].x=;
FFT(fn,a,); FFT(fn,b,);
for (int i=; i<fn; ++i)
a[i]=a[i]*a[i], b[i]=b[i]*b[i];
FFT(fn,a,-); FFT(fn,b,-);
for (int i=; i<fn; ++i)
{
int x=(a[i].x+b[i].x+0.5);
x=(x+)>>;
Re=(Re+p[x]-)%MOD;
}
printf("%lld\n",(Re-fun+MOD)%MOD);
}

最新文章

  1. C语言栈调用机制初探
  2. 【cpp】Vector
  3. Java内存泄露简述
  4. 对Objective-C相关的类、方法、属性、成员变量介绍
  5. Google推Android新开发语言Sky:流畅度 秒iOS
  6. matlab GUI之 -- 绘图
  7. jQuery 属性操作 - attr() 方法
  8. mongDB数据库 小白学习
  9. mongodb聚合命令
  10. 简单聊聊Linux学习经历
  11. socket 10060错误解决方案
  12. c++ &lt;vector&gt;学习
  13. CF 888E Maximum Subsequence
  14. Markdown 字体
  15. 遇到返回键会退到页面的问题(window.location)
  16. C#右下角弹出消息框
  17. testNG断言
  18. JavaScript修改注册表
  19. 关于安装时无法重启rabbitmq服务
  20. The power of now

热门文章

  1. 手把手教你写一个java的orm(完)
  2. 比较ArrayList和LinkedList的异同
  3. 解决:java 读取 resources 下面的 json 文件
  4. manven springmvc 项目中 slf4j 的配置使用(结合log4j 或者 logback)
  5. ManualResetEvent
  6. AIX修改时区,配置NTP服务
  7. C# Visual 快捷键
  8. U-Push 3.1.5SDK 集成的一些坑
  9. 基于 Docker 的现代软件供应链
  10. PHP生成随机或者唯一字符串