热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

BZOJ3160:万径人踪灭

FFT+Manacher.

FFT+Manacher.



不连续只需要减去连续的就可以了,连续的可以直接Manacher算出来.

其他全部对称的回文子序列就可以用生成函数那样FFT搞出来,把ab分开考虑就行.



有挺多细节的...包括下标运算什么什么的...

/**************************************************************
Problem: 3160
User: BeiYu
Language: C++
Result: Accepted
Time:3868 ms
Memory:29616 kb
****************************************************************/
#include bits/stdc++.h
using namespace std;
#define mpr make_pair
#define rr first
#define ii second
typedef pair double,double Complex;
typedef long long LL;
const int N = 5e5+50;
const long long p = 1e9+7;
const double Pi = M_PI;
Complex operator + (const Complex a,const Complex b) {
return mpr(a.rr+b.rr,a.ii+b.ii);
}
Complex operator - (const Complex a,const Complex b) {
return mpr(a.rr-b.rr,a.ii-b.ii);
}
Complex operator * (const Complex a,const Complex b) {
return mpr(a.rr*b.rr-a.ii*b.ii,a.rr*b.ii+a.ii*b.rr);
int n,l;
LL ans;
int f[N],g[N];
char t[N],s[N];
Complex a[N],b[N],c[N];
LL Pow(LL a,LL b,LL r=1) { for(;b;b =1,a=a*a%p) if(b 1) r=r*a%p;return r; }
void Manacher(char *t) {
int ll=0;
for(int i=0;i i++) s[ll++]='#',s[ll++]=t[i];
s[0]='$',s[ll++]='@';
for(int i=0,j=0,mx=0;i i++) {
if(mx i) f[i]=min(mx-i,f[j*2-i]);else f[i]=1;
while(i+f[i] ll i-f[i] =0 s[i+f[i]]==s[i-f[i]]) f[i]++;
if(i+f[i] mx) mx=i+f[i],j=i;
}
void init(int x) {
for(n=1;n n =1);n =1;
}
void Rev(Complex a[]) {
for(int i=0,j=0;i i++) {
if(i j) swap(a[i],a[j]);
for(int k=n 1;(j^=k) k =1);
}
}
void DFT(Complex a[],int r=1) {
Rev(a);
for(int i=2;i i =1) {
Complex wi=mpr(cos(2.0*Pi/i),r*sin(2.0*Pi/i));
for(int k=0;k k+=i) {
Complex w=mpr(1.0,0.0);
for(int j=k;j k+i/2;j++) {
Complex t1=a[j],t2=w*a[j+i/2];
a[j]=t1+t2,a[j+i/2]=t1-t2;
w=w*wi;
}
}
}
if(r==-1) for(int i=0;i i++) a[i].rr/=n;
}
void FFT(Complex a[],Complex b[],Complex c[]) {
DFT(a),DFT(b);
for(int i=0;i i++) c[i]=a[i]*b[i];
DFT(c,-1);
int main() {
scanf("%s",t);
l=strlen(t);
init(l);
for(int i=0;i i++) a[i]=mpr(t[i]=='a',0),b[i]=a[i];
// reverse(b,b+l);
// for(int i=0;i i++) cout (int)a[i].rr " ";cout endl;
// for(int i=0;i i++) cout (int)b[i].rr " ";cout endl;
FFT(a,b,c);
for(int i=0;i i++) g[i]=(int)(c[i].rr+0.5);
// for(int i=0;i i++) cout (int)(c[i].rr+0.5) " ";cout endl;
memset(a,0,sizeof(a)),memset(b,0,sizeof(b));
for(int i=0;i i++) a[i]=mpr(t[i]=='b',0),b[i]=a[i];
// reverse(b,b+l);
// for(int i=0;i i++) cout (int)a[i].rr " ";cout endl;
// for(int i=0;i i++) cout (int)b[i].rr " ";cout endl;
FFT(a,b,c);
for(int i=0;i i++) g[i]+=(c[i].rr+0.5);
// for(int i=0;i i++) cout (int)(c[i].rr+0.5) " ";cout endl;
for(int i=0;i i++) g[i]=(g[i]+1)/2;
// for(int i=0;i i++) cout g[i] " ";cout endl;
Manacher(t);
// for(int i=0;i i++) cout f[i] " ";cout endl;
for(int i=0;i l*2+1;i++) if(!(i 1)) f[i]-=1;
// for(int i=0;i i++) cout f[i] " ";cout endl;
for(int i=0;i l*2-1;i++) ans=(ans+Pow(2,g[i])-(f[i+1]+1)/2-1)%p;
cout ans endl;
return 0;
}
/*
abaabaa
#bbb#
##aa
53


   



推荐阅读
  • 本文介绍如何利用栈数据结构在C++中判断字符串中的括号是否匹配。通过顺序栈和链栈两种方式实现,并详细解释了算法的核心思想和具体实现步骤。 ... [详细]
  • 本文介绍如何从字符串中移除大写、小写、特殊、数字和非数字字符,并提供了多种编程语言的实现示例。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • HDU 2871 内存管理问题(线段树优化)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871。本题涉及内存管理操作,包括重置、申请、释放和查询内存块。通过使用线段树进行高效管理和维护。 ... [详细]
  • 本文深入探讨了UNIX/Linux系统中的进程间通信(IPC)机制,包括消息传递、同步和共享内存等。详细介绍了管道(Pipe)、有名管道(FIFO)、Posix和System V消息队列、互斥锁与条件变量、读写锁、信号量以及共享内存的使用方法和应用场景。 ... [详细]
  • KMP算法是处理字符串匹配的一种高效算法它首先用O(m)的时间对模板进行预处理,然后用O(n)的时间完成匹配。从渐进的意义上说,这样时间复 ... [详细]
  • 本文介绍了一个经典的算法问题——活动选择问题,来源于牛客网的比赛题目。该问题要求从一系列活动集合中选出最多数量的相容活动,确保这些活动的时间段不重叠。 ... [详细]
  • 本文详细解析了2019年西安邀请赛中的一道树形动态规划题目——J题《And And And》。题目要求计算树中所有子路径异或值为0的集合数量,通过深入分析和算法优化,提供了高效的解决方案。 ... [详细]
  • 本文详细介绍了8051系列微控制器的中断系统,特别是C51编译器中interrupt和using关键字的作用及其使用方法。通过深入分析这两个关键字的功能,帮助开发者更好地理解和优化中断程序的设计。 ... [详细]
  • 本文详细解释了为什么在成功执行移动赋值操作后,对象的析构函数会被调用,并提供了代码示例和详细的分析。 ... [详细]
  • Linux环境下进程间通信:深入解析信号机制
    本文详细探讨了Linux系统中信号的生命周期,从信号生成到处理函数执行完毕的全过程,并介绍了信号编程中的注意事项和常见应用实例。通过分析信号在进程中的注册、注销及处理过程,帮助读者理解如何高效利用信号进行进程间通信。 ... [详细]
  • 本文探讨了符号三角形问题,该问题涉及由相同数量的“+”和“-”符号组成的三角形。通过递归回溯法,可以有效地搜索并计算符合条件的符号三角形的数量。 ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 主调|大侠_重温C++ ... [详细]
  • 本文详细介绍了C语言中的基本数据类型,包括整型、浮点型、字符型及其各自的子类型,并探讨了这些类型在不同编译环境下的表现。 ... [详细]
author-avatar
惜洛妍_311
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有