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

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #define N (400009)
 6 #define LL long long
 7 #define MOD (1000000007)
 8 using namespace std;
 9
10 int n,fn,l,tot,r[N],len[N],p[N];
11 LL Re,fun;
12 char s[N],st[N];
13 double pi=acos(-1.0);
14 struct complex
15 {
16     double x,y;
17     complex (double xx=0,double yy=0)
18     {
19         x=xx; y=yy;
20     }
21 }a[N],b[N];
22
23 complex operator + (complex a,complex b) {return complex(a.x+b.x,a.y+b.y);}
24 complex operator - (complex a,complex b) {return complex(a.x-b.x,a.y-b.y);}
25 complex operator * (complex a,complex b) {return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
26 complex operator / (complex a,double b) {return complex(a.x/b,a.y/b);}
27
28 void FFT(int n,complex *a,int opt)
29 {
30     for (int i=0; i<n; ++i)
31         if (i<r[i]) swap(a[i],a[r[i]]);
32     for (int k=1; k<n; k<<=1)
33     {
34         complex wn=complex(cos(pi/k),opt*sin(pi/k));
35         for (int i=0; i<n; i+=k<<1)
36         {
37             complex w=complex(1,0);
38             for (int j=0; j<k; ++j,w=w*wn)
39             {
40                 complex x=a[i+j], y=w*a[i+j+k];
41                 a[i+j]=x+y; a[i+j+k]=x-y;
42             }
43         }
44     }
45     if (opt==-1) for (int i=0; i<n; ++i) a[i]=a[i]/n;
46 }
47
48 void Manacher()
49 {
50     s[++tot]='('; s[++tot]='#';
51     for (int i=0; i<n; ++i)
52         s[++tot]=st[i], s[++tot]='#';
53     s[++tot]=')';
54     int maxn=0,mid=0,x;
55     for (int i=1; i<=tot; ++i)
56     {
57         if (i>maxn) x=1;
58         else x=min(maxn-i+1,len[mid*2-i]);
59         while (s[i+x]==s[i-x]) x++;
60         len[i]=x;
61         if (i+x-1>maxn) maxn=i+x-1, mid=i;
62         fun=(fun+len[i]/2)%MOD;
63     }
64 }
65
66 int main()
67 {
68     p[0]=1;
69     for (int i=1; i<=100000; ++i)
70         p[i]=p[i-1]*2%MOD;
71     scanf("%s",st);    n=strlen(st);
72     Manacher();
73
74     fn=1;
75     while (fn<=n+n) fn<<=1, l++;
76     for (int i=0; i<fn; ++i)
77         r[i]=(r[i>>1]>>1) | ((i&1)<<(l-1));
78     for (int i=0; i<n; ++i)
79         if (st[i]=='a') a[i].x=1;
80         else b[i].x=1;
81     FFT(fn,a,1); FFT(fn,b,1);
82     for (int i=0; i<fn; ++i)
83         a[i]=a[i]*a[i], b[i]=b[i]*b[i];
84     FFT(fn,a,-1); FFT(fn,b,-1);
85     for (int i=0; i<fn; ++i)
86     {
87         int x=(a[i].x+b[i].x+0.5);
88         x=(x+1)>>1;
89         Re=(Re+p[x]-1)%MOD;
90     }
91     printf("%lld\n",(Re-fun+MOD)%MOD);
92 }

转载于:https://www.cnblogs.com/refun/p/10091484.html

BZOJ3160:万径人踪灭(FFT,Manacher)相关推荐

  1. 洛谷P4199 万径人踪灭(manacher+FFT)

    传送门 题目所求为所有的不连续回文子序列个数,可以转化为回文子序列数-回文子串数 回文子串manacher跑一跑就行了,考虑怎么求回文子序列数 我们考虑,如果$S_i$是回文子序列的对称中心,那么只要 ...

  2. BZOJ 3160 FFT+Manacher

    思路: 这道题思路好奇怪--. 我们先要知道关于x (x可以是间隙) 对称的有几对字母 显然暴力是n^2的 那怎么办呢 先把所有'a'看成1 'b'看成0 意外的发现 这不就是卷积嘛 再倒过来搞一搞 ...

  3. BZOJ3160:万径人踪灭

    Description Input & Output & Sample Input & Sample Output HINT 题解: 题意即求不连续但间隔长度对称的回文串个数. ...

  4. BZOJ3160: 万径人踪灭

    设a[i]=bool(s[i]=='a'),b[i]=bool(s[i]=='b'),考虑a和a.b和b的卷积,由于卷积是对称的,就可以统计出不连续回文子串个数了.可能说得比较简略.再用manache ...

  5. manacher算法学习(求最长回文子串长度)

    Manacher总结 我的代码 学习:yyb luogu题目模板 xzy的模板 #include<iostream> #include<cstdlib> #include< ...

  6. 【BZOJ3160】万径人踪灭 Manacher+FFT

    [BZOJ3160]万径人踪灭 Description Input Output Sample Input Sample Output HINT 题解:自己想出来1A,先撒花~(其实FFT部分挺裸的) ...

  7. 【BZOJ3160】 万径人踪灭(FFT,manacher)

    前言 多项式真的很难♂啊qwq Solution 考虑求的是一个有间隔的回文串,相当于是: 总的答案-没有间隔的答案 考虑总的答案怎么计算?FFT卷一下就好了. 对于每一位字符,有两种取值,然后随便卷 ...

  8. 【BZOJ 3160】 3160: 万径人踪灭 (FFT)

    3160: 万径人踪灭 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 1440  Solved: 799 Description Input Out ...

  9. 【bzoj3160】万径人踪灭

    题意:给一个只含a.b的字符串,求所有的回文不连续子序列. manacher+FFT. 先求出所有回文序列,再减去连续子序列(即回文串). 将a.b分开考虑,对于一个对称轴,以其为回文中心的回文序列的 ...

  10. bzoj3160(FFT+回文自动机)

    题目描述 https://www.lydsy.com/JudgeOnline/problem.php?id=3160 题解 先把问题转化一下,我们要求的是非连续对称回文子序列. ans=回文子序列数- ...

最新文章

  1. return error怎么定义_SpringBoot 系列 web 篇之自定义返回 Http Code 的 n 种姿势
  2. ios3怎么取消长按弹出菜单_苹果:iOS13取消3D-Touch重压改为长按只是个BUG~
  3. 王道408数据结构——第二章 线性表
  4. PHP通知弹窗代码_公告弹窗
  5. 深度学习《Photo Editing》
  6. ffmpeg前景_5G时代音视频开发前景怎么样?音视频开发需要掌握哪些技术?
  7. 利用Windows的启动机制实现拦截360的运行
  8. HashPasswordForStoringInConfigFile 已过时
  9. pandownload搜索引擎脚本
  10. ubuntu字体丑_科学网—关于ubuntu系统的一点经验——字体崩溃 - 苗玉虎的博文
  11. Android 混淆配置
  12. [Loj 6070][回文树+可持久化线段树+border理论]基因
  13. UFS系列三:UFS数据包UPIU
  14. java 开发脚本视频_你写脚本,AI自动剪视频:13分钟完成剪辑师7小时创作
  15. Shell脚本循环语句及exit、continue和break用法
  16. 2021-7-14-超融合基础知识
  17. python神经网络算法pdf_高清图解:神经网络、机器学习、数据科学一网打尽|附PDF...
  18. 阿里一日游,入职当天即提辞职
  19. dom4j 获取xml中指定节点的信息
  20. python情感分析:基于jieba的分词及snownlp的情感分析!

热门文章

  1. 8岁学编程,入行近40年,我总结了15条程序员经验宝典”
  2. [CF1019C]Sergey's problem[构造]
  3. A营Tim-Fang主页代码
  4. 【置顶】常用英文单词
  5. 前后端对称加密(AES)
  6. 朱赟的技术管理课阅读笔记
  7. 氧化应激损伤beita细胞
  8. 自主招生专转本计算机考啥,普通高校专转本自主招生
  9. Hololens 2 修改图标icon
  10. Python: random模块微信红包算法(二倍均值法)