【BZOJ3160】万径人踪灭 Manacher+FFT

【BZOJ3160】万径人踪灭

Description

Input

Output

Sample Input

Sample Output

HINT

题解:自己想出来1A,先撒花~(其实FFT部分挺裸的)

做这道题,第一思路很重要,显然看到这题的第一想法就是ans=总数-不合法(不要问我为什么显然)。因为向这种用补集法的题一般都会给一些很奇葩的限制条件,但是一旦换个角度去想就很水了,好了不多说废话了。

显然,不合法的情况,也就是连续的回文区间的方案数,我们直接上Manacher就搞定了嘛!答案就是所有对称轴的(最长回文串长度+1)/2之和(是的,很显然)

对于不合法的情况,我们发现两串对称的情况跟卷积的形式类似(FFT做多了吧?),但是问题来了,怎么构造出一个卷积,使得它的值就是回文子串的个数呢?

我们发现原串只有a或b,所以思考能不能构造出一种卷积,使得对应位置的值跟下面一样

a*b->0       b*a->0        a*a->1     b*b->1

如果把a看成0,b看成1,这显然是一个异或,然而并没什么卵用。但我们如果把a看成0,b看成1,可以满足只有b*b是1,其他都是0;同理,把a看成1,b看成0,可以满足只有a*a是1,其他都是0,然后我们对这两种情况分别求一次卷积,就能得到:以i为对称中心的最长子序列的回文半径长度。这里注意一下,用于是两个一样的多项式相乘,所以每对字符会被算成两次(单个字符自我对称的除外),所以我们要的回文半径应该是(x+1)/2

然而半径长度并不是方案数,由于每对对称的字符都可以选或不选,所以对答案的贡献就是2^长度-1(因为你不能一个也不选吧?)

好吧,感觉说了这么多又有点说不明白了,所以欢迎提问和hack~

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#define pi acos(-1.0)
#define mod 1000000007
using namespace std;
int n,ans;
struct cp
{double x,y;cp (double a,double b){x=a,y=b;}cp (){}cp operator + (cp a){return cp(x+a.x,y+a.y);}cp operator - (cp a){return cp(x-a.x,y-a.y);}cp operator * (cp a){return cp(x*a.x-y*a.y,x*a.y+y*a.x);}
}n1[1<<20],n2[1<<20];
int s[1<<20],ret[1<<20],rl[1<<20],pn[1<<20];
char str[1<<20];
void FFT(cp *a,int len,int f)
{int i,j,k,h;cp t;for(i=k=0;i<len;i++){if(i>k)	swap(a[i],a[k]);for(j=(len>>1);(k^=j)<j;j>>=1);}for(h=2;h<=len;h<<=1){cp wn(cos(f*2*pi/h),sin(f*2*pi/h));for(j=0;j<len;j+=h){cp w(1.0,0);for(k=j;k<j+h/2;k++)	t=w*a[k+h/2],a[k+h/2]=a[k]-t,a[k]=a[k]+t,w=w*wn;}}
}
void work(cp *a,cp *b,int len)
{FFT(a,len,1),FFT(b,len,1);for(int i=0;i<len;i++)	a[i]=a[i]*b[i];FFT(a,len,-1);for(int i=0;i<len;i++)	ret[i]+=(int)(a[i].x/len+0.1);
}
int main()
{scanf("%s",str);int i,mx,pos,len=strlen(str);for(i=0;i<len;i++)	s[n++]=0,s[n++]=str[i]-'a';s[n++]=0;for(mx=-1,i=0;i<n;i++){if(mx>i)	rl[i]=min(mx-i+1,rl[2*pos-i]);else	rl[i]=1;for(;i+rl[i]<n&&rl[i]<=i&&s[i+rl[i]]==s[i-rl[i]];rl[i]++);if(mx<i+rl[i]-1)	mx=i+rl[i]-1,pos=i;}for(i=0;i<n;i++)	ans=(ans-rl[i]/2+mod)%mod;for(len=1;len<2*n;len<<=1);for(i=0;i<len;i++)	n1[i]=n2[i]=cp(0,0);for(i=1;i<n;i+=2)	n1[i]=n2[i]=cp(s[i],0);work(n1,n2,len);for(i=0;i<len;i++)	n1[i]=n2[i]=cp(0,0);for(i=1;i<n;i+=2)	n1[i]=n2[i]=cp(s[i]^1,0);work(n1,n2,len);for(pn[0]=i=1;i<=n;i++)	pn[i]=(pn[i-1]<<1)%mod;for(i=0;i<n;i++)	ans=(ans+pn[(ret[i<<1]+(i&1))>>1]-1)%mod;printf("%d",ans);return 0;
}

 

转载于:https://www.cnblogs.com/CQzhangyu/p/6890700.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/269331.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ADOMD.net概述

ADOMD.NET是一个标准的.NET数据提供者&#xff0c;它主要用来与多维数据源进行通信。它使用支持 XML for Analysis version 1.1标准的数据提供者连接数据源&#xff0c;使用TCP/IP或 HTTP流传输和接受SOAP请求。使用ADOMD.NET可以获取和操作多维数据&#xff0c;KPI和挖掘模型。…

Python 环境搭建

本章节我们将向大家介绍如何在本地搭建Python开发环境。Python可应用于多平台包括 Linux 和 Mac OS X。你可以通过终端窗口输入 "python" 命令来查看本地是否已经安装Python以及Python的安装版本。Unix (Solaris, Linux, FreeBSD, AIX, HP/UX, SunOS, IRIX, 等等。)W…

SHOW VARIABLES LIKE “tx_isolation“查看mysql查看当前数据库的事物隔离级别

SHOW VARIABLES LIKE "tx_isolation"查看mysql查看当前数据库的事物隔离级别

[大数据]-Fscrawler导入文件(txt,html,pdf,worf...)到Elasticsearch5.3.1并配置同义词过滤...

fscrawler是ES的一个文件导入插件&#xff0c;只需要简单的配置就可以实现将本地文件系统的文件导入到ES中进行检索&#xff0c;同时支持丰富的文件格式&#xff08;txt.pdf,html,word...&#xff09;等等。下面详细介绍下fscrawler是如何工作和配置的。 一、fscrawler的简单使…

字幕小工具 SubTool Released

过年后, 才觉得我老早就装好的Vista应该拿来做开发平台,于是安装上了VS 2005, 和SP1, 也装上了VS 2005 Patch for Vista3月份忙里偷闲写了这样一个小工具,去年一直都在用VS2003, 我本意是希望借此来学习VS2005的新东西的从技术上来说:里面使用了Nini,来读取和保存INI文件使用了…

今天辞职~Scars of time

“再长久&#xff0c;之于时光&#xff0c;仅是一瞬;再短暂&#xff0c;之于我心&#xff0c;亦是永恒” 曾经,有人….从第一本<女神的圣斗士>,喜欢上了漫画. 这件事情,会在小学六年级的时候发生,那时去海边玩,爸爸偷偷给他买了那本<激斗,白鸟对天蝎!>从第一次玩&l…

jQuery中的height()、innerheight()、outerheight()的区别总结

在前端jQuery代码中突然看到outerheight(),第一感觉就是&#xff0c;这是什么鬼&#xff1f;然后仔细查阅了一下&#xff0c;居然发现还有这么多相似的东西。 在jQuery中&#xff0c;获取元素高度的函数有3个&#xff0c;它们分别是height()、 innerHeight()、outerHeight()。 …

自然语言之情感分析(中文)

自然语言之情感分析(中文) 数据来源&#xff1a;香港金融新闻平台处理工具&#xff1a;python3.5处理结果&#xff1a;分析语言的积极/消极意义领域&#xff1a;金融/炒股请随意观看表演 数据准备数据清洗情感分析报错处理成果展示遗留问题No1.数据准备 准备工作主要是对字典进…

MySQL的IFNULL() 函数使用

IFNULL() 函数用于判断第一个表达式是否为 NULL&#xff0c;如果为 NULL 则返回第二个参数的值&#xff0c;如果不为 NULL 则返回第一个参数的值。 IFNULL() 函数语法格式为&#xff1a; IFNULL(expression, alt_value) 如果第一个参数的表达式 expression 为 NULL&#xff…

[51nod1264]线段相交

给定两个点: typedef struct { double x, y; } Point; Point A1,A2,B1,B2; 首先引入两个实验&#xff1a; a.快速排斥实验 设以线段A1A2和线段B1B2为对角线的矩形为M,N; 若M,N 不相交&#xff0c;则两个线段显然不相交&#xff1b; 所以&#xff1a;满足第一个条件时&#xf…

Qt 在designer 中给QToolBar 添加 action控件

Qt 在designer 中给QToolBar 添加 action控件 1.在action editor 添加控件 SendData不出现使用打钩时 2. 使用鼠标直接拖拽到Ui指定位置

Windows环境下通过Git来管理自己的Android代码

前面已经介绍了在Windows下使用git工具来下载Android的源代码&#xff0c;Windows环境下通过Git得到Android源代码&#xff0c;这里记录我使用git工具来管理我自己的代码&#xff0c;git是一种分布式的项目管理工具而CVS及SVN都是集中式的版本号控制系统集中式版本号控制系统最…