【BZOJ 4503】4503: 两个串 (FFT)
4503: 两个串
Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 497 Solved: 226Description
兔子们在玩两个串的游戏。给定两个字符串S和T,兔子们想知道T在S中出现了几次,分别在哪些位置出现。注意T中可能有“?”字符,这个字符可以匹配任何字符。Input
两行两个字符串,分别代表S和TOutput
第一行一个正整数k,表示T在S中出现了几次接下来k行正整数,分别代表T每次在S中出现的开始位置。按照从小到大的顺序输出,S下标从0开始。Sample Input
bbabaababaaaaabaaaaaaaabaaabbbabaaabbabaabbbbabbbbbbabbaabbbababababbbbbbaaabaaabbbbbaabbbaabbbbabab
a?aba?abbaSample Output
0HINT
S 长度不超过 10^5, T 长度不会超过 S。 S 中只包含小写字母, T中只包含小写字母和“?”Source
【分析】
这题做了我好久啊。。幸好1A,哭死了。。
首先,是不可以用KMP的,【我一开始还觉得可以】
因为你根据第二个串求next可能会以'?'为媒介,认为'a'与'b'相同什么的。
小山羊说,大多数含'?'的字符串的题目都不可以用KMP,EXKMP,AC自动机,后缀数组等等字符串匹配方法,就会出现上面说的问题。不过我觉得如果这题的'?'是在第一个串上的话,应该是可以用的。
所以怎么办呢?FFT大法。
很容易想到一个方法就是类似‘万径人踪灭’那里的。做26次FFT,每次把一个字母标为1,其他标为0,看一看匹配长度是否为m,但是会超时?【并没有实测过
不过这题只是问你能否完全匹配,并没有问你匹配多少个字符之类的。
所以可以构造这么一个函数。设$a[i]=s[i]=='?'?0:a[i]-'a'+1$。
则$ans[i+j]=(a[i]-b[j])^{2}*b[j]$
当且仅当全部匹配,ans为0,后面乘a[j]是搞'?'的。
这个也很显然吧。
但是!!!注意这个式子啊,不能把a,b化成点值表示就直接乘,否则意义就会变成
$ans[i+i+j]+=a[i]^{2}*a[j]; ans[j+j+j]+=a[j]^{3}; ans[i+j+j]+=-2*a[i]*a[j]^{2}$意义完全不对。
我还是理解了好久才发现这个错啊,以后不能再错这个了!!!
所以你要分几次搞,令$A[i]=a[i]^2$,$B[i]=b[i]^2$,$C[i]=1$,$D[i]=b[i]^{3}$
则$ans=A*b+C*D-2*a*B$
FFT加速即可【为什么我跑得那么慢并且代码那么丑?
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define Maxn 100010*4
const double pi=acos(-); char s1[Maxn],s2[Maxn];
int aa[Maxn],bb[Maxn]; struct P
{
double x,y;
P() {x=y=;}
P(double x,double y):x(x),y(y){}
friend P operator + (P x,P y) {return P(x.x+y.x,x.y+y.y);}
friend P operator - (P x,P y) {return P(x.x-y.x,x.y-y.y);}
friend P operator * (P x,P y) {return P(x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x);}
friend P operator * (P x,int y) {return P(x.x*y,x.y*y);}
}a[Maxn],b[Maxn]; int nn,R[Maxn],op[Maxn],ans[Maxn];
void fft(P *s,int f)
{
for(int i=;i<nn;i++) if(i<R[i]) swap(s[i],s[R[i]]);
for(int i=;i<nn;i<<=)
{
P wn(cos(pi/i),f*sin(pi/i));
for(int j=;j<nn;j+=i<<)
{
P w(,);
for(int k=;k<i;k++,w=w*wn)
{
P x=s[j+k],y=w*s[j+k+i];
s[j+k]=x+y;s[j+k+i]=x-y;
}
}
}
if(f==-)
{
for(int i=;i<=nn;i++) s[i].x=s[i].x/nn;
}
} int main()
{
scanf("%s%s",s1,s2);
int n=strlen(s1),m=strlen(s2);
n--;m--;
for(int i=;i<=n;i++) aa[i]=s1[i]=='?'?:(s1[i]-'a'+);
for(int i=;i<=m;i++) bb[m-i]=s2[i]=='?'?:(s2[i]-'a'+);
int ll=;nn=;
while(nn<=n+m) ll++,nn<<=;
for(int i=;i<nn;i++) R[i]=(R[i>>]>>)|((i&)<<(ll-)); for(int i=;i<=n;i++) a[i].x=aa[i]*aa[i];
for(int i=;i<=m;i++) b[i].x=bb[i];
fft(a,);fft(b,);
for(int i=;i<=nn;i++) a[i]=a[i]*b[i];
fft(a,-);
memset(ans,,sizeof(ans));
for(int i=;i<=n+m;i++) ans[i]+=(int)(a[i].x+0.5);
// for(int i=0;i<=n+m;i++) printf("%d ",ans[i]); for(int i=;i<=nn;i++) a[i].x=a[i].y=b[i].x=b[i].y=;
for(int i=;i<=n;i++) a[i].x=;
for(int i=;i<=m;i++) b[i].x=bb[i]*bb[i]*bb[i];
fft(a,);fft(b,);
for(int i=;i<=nn;i++) a[i]=a[i]*b[i];
fft(a,-);
for(int i=;i<=n+m;i++) ans[i]+=(int)(a[i].x+0.5);
// for(int i=0;i<=n+m;i++) printf("%d ",ans[i]); for(int i=;i<=nn;i++) a[i].x=a[i].y=b[i].x=b[i].y=;
for(int i=;i<=n;i++) a[i].x=*aa[i];
for(int i=;i<=m;i++) b[i].x=bb[i]*bb[i];
fft(a,);fft(b,);
for(int i=;i<=nn;i++) a[i]=a[i]*b[i];
fft(a,-);
for(int i=;i<=n+m;i++) ans[i]-=(int)(a[i].x+0.5);
// for(int i=0;i<=n+m;i++) printf("%d ",ans[i]);printf("\n"); op[]=;
for(int i=m;i<=n;i++) if(!ans[i])
{
op[++op[]]=i-m;
}
printf("%d\n",op[]);
for(int i=;i<=op[];i++) printf("%d\n",op[i]);
return ;
}
2017-04-14 2017-04-14
【BZOJ 4503】4503: 两个串 (FFT)的更多相关文章
- BZOJ 4503: 两个串 [FFT]
4503: 两个串 题意:兔子们在玩两个串的游戏.给定两个只含小写字母的字符串S和T,兔子们想知道T在S中出现了几次, 分别在哪些位置出现.注意T中可能有"?"字符,这个字符可以匹 ...
- 【bzoj4259/bzoj4503】残缺的字符串/两个串 FFT
bzoj4259 题目描述 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有 ...
- 【BZOJ4503】两个串 FFT
[BZOJ4503]两个串 Description 兔子们在玩两个串的游戏.给定两个字符串S和T,兔子们想知道T在S中出现了几次, 分别在哪些位置出现.注意T中可能有“?”字符,这个字符可以匹配任何字 ...
- BZOJ.4503.两个串(FFT/bitset)
题目链接 \(Description\) 给定两个字符串S和T,求T在S中出现了几次,以及分别在哪些位置出现.T中可能有'?'字符,这个字符可以匹配任何字符. \(|S|,|T|\leq 10^5\) ...
- bzoj 4503 两个串——FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4503 翻转T,就变成卷积.要想想怎么判断. 因为卷积是乘积求和,又想到相等的话相减为0,所以 ...
- bzoj 4503 两个串 —— FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4503 推式子即可: 不知怎的调了那么久,应该是很清晰的. 代码如下: #include< ...
- BZOJ 4503 两个串 ——FFT
[题目分析] 定义两个字符之间的距离为 (ai-bi)^2*ai*bi 如果能够匹配,从i到i+m的位置的和一定为0 但这和暴力没有什么区别. 发现把b字符串反过来就可以卷积用FFT了. 听说KMP+ ...
- 【bzoj4503】 两个串 FFT
$FFT$套路题(然而我看错题了) 我们考虑化一下式子. 设当前比较的两个部分为$S[i....i+|T|-1]$和$T[0....|T|-1]$. 我们对串$T$中出现问号的位置全部赋值为$0$. ...
- bzoj 4503 两个串
Description 兔子们在玩两个串的游戏.给定两个字符串S和T,兔子们想知道T在S中出现了几次, 分别在哪些位置出现.注意T中可能有“?”字符,这个字符可以匹配任何字符. Input 两行两个字 ...
随机推荐
- 【HDU】6110 路径交(2017百度之星) 线段树+RMQ-LCA+树链的交
[题目]2017"百度之星"程序设计大赛 - 初赛(A) [题意]给定n个点的带边权树,m条编号1~m的路径,Q次询问编号区间[L,R]所有链的交集的长度.n<=500000 ...
- Chrome浏览器任意修改网页内容
在Chrome浏览器按F12,打开开发者工具,切换到console选项卡: 在下面的输入行输入下面的命令回车: document.body.contentEditable="true&quo ...
- 【Windows使用笔记】神舟笔记本的control center
首先,神船大法好. 然后,因为我的船风扇声音有点大啊,在实验室感觉就很吵,但是它的背板温度又不是很高,所以想设置下风扇的启动. 所以需要用到神船自带的control center软件. 长这样. 应该 ...
- FPGA与CPLD的概念及其区别
一.FPGA与CPLD的基本概念 1.CPLD CPLD主要是由可编程逻辑宏单元(LMC,Logic Macro Cell)围绕中心的可编程互连矩阵单元组成,其中LMC逻辑结构较复杂,并具有复杂的I/ ...
- 创建一个简单的Maven工程
Maven的工程结构如下图所示: 大致来看,Maven的工程结构如下: 在创建maven工程时,可以通过骨架创建,也可以不通过骨架创建. 我们先用idea通过骨架创建一个Maven工程. 配置pom. ...
- java版云笔记(七)之事务管理
事务管理 事务:程序为了保证业务处理的完整性,执行的一条或多条SQL语句. 事务管理:对事务中的SQL语句进行提交或者回滚. 事物管理对于企业应用来说是至关重要的,好使出现异常情况,它也可以保证数据的 ...
- MVC开发模式与javaEE三层架构
1.MVC开发模式 1. M:Model,模型.JavaBean * 完成具体的业务操作,如:查询数据库,封装对象2. V:View,视图.JSP * 展示数据3. C:C ...
- python抓取链家房源信息(三)
之前写过一个链家网北京二手房的数据抓取,然后本来今天想着要把所有的东西弄完,但是临时有事出去了一趟,耽搁了一下,然后现在是想着把北京的二手房的信息都进行抓取,并且存储在mongodb中, 首先是通过' ...
- Python股票信息抓取(三)
最近在看mongodb,然后会用了一些最简单的mongodb的操作,然后想着结合股票信息的数据的抓取,然后将数据存储在mongodb中,对于mongo和数据库的最大的区别是,mongo不需要建表,直接 ...
- Sublime Text 2之Emmet插件安装及使用
1.安装Emmet How To Install?Reffer to this link:http://www.ituring.com.cn/article/47310 2.使用Emmet--Abbr ...