Description

很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n。可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺。
你想对这两个串重新进行匹配,其中A为模板串,那么现在问题来了,请回答,对于B的每一个位置i,从这个位置开始连续m个字符形成的子串是否可能与A串完全匹配?

Input

第一行包含两个正整数m,n(1<=m<=n<=300000),分别表示A串和B串的长度。
第二行为一个长度为m的字符串A。
第三行为一个长度为n的字符串B。
两个串均仅由小写字母和*号组成,其中*号表示相应位置已经残缺。

Output

第一行包含一个整数k,表示B串中可以完全匹配A串的位置个数。
若k>0,则第二行输出k个正整数,从小到大依次输出每个可以匹配的开头位置(下标从1开始)。

Sample Input

3 7
a*b
aebr*ob

Sample Output

2
1 5

Solution

FFT好神啊还能做字符串的题(逃
 

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define N (1200000+1000)
using namespace std; double pi=acos(-1.0),F[N];
int n,m,fn,l,r[N],A[N],B[N];
int ans_num,ans[N];
char stA[N],stB[N];
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;
} int main()
{
scanf("%d%d",&m,&n);
scanf("%s%s",stA+,stB+);
for (int i=; i<=m; ++i) A[m-i+]=(stA[i]=='*')?:stA[i]-'a'+;
for (int i=; i<=n; ++i) B[i]=(stB[i]=='*')?:stB[i]-'a'+;
m++; n++;//因为我是字符串AB都向右移了一位,则计算出来的答案应该是向右移动两位的,故这里要+1 fn=;
while (fn<=n+m) fn<<=,l++;
for (int i=; i<fn; ++i)
r[i]=(r[i>>]>>) | ((i&)<<(l-)); memset(a,,sizeof(a)); memset(b,,sizeof(b));
for (int i=; i<=n; ++i)
a[i].x=A[i]*A[i]*A[i],b[i].x=B[i];
FFT(fn,a,); FFT(fn,b,);
for (int i=; i<=fn; ++i)
a[i]=a[i]*b[i];
FFT(fn,a,-);
for (int i=; i<=n; ++i)
F[i]+=a[i].x; memset(a,,sizeof(a)); memset(b,,sizeof(b));
for (int i=; i<=n; ++i)
a[i].x=A[i]*A[i],b[i].x=B[i]*B[i];
FFT(fn,a,); FFT(fn,b,);
for (int i=; i<=fn; ++i)
a[i]=a[i]*b[i];
FFT(fn,a,-);
for (int i=; i<=n; ++i)
F[i]-=*a[i].x; memset(a,,sizeof(a)); memset(b,,sizeof(b));
for (int i=; i<=n; ++i)
a[i].x=A[i],b[i].x=B[i]*B[i]*B[i];
FFT(fn,a,); FFT(fn,b,);
for (int i=; i<=fn; ++i)
a[i]=a[i]*b[i];
FFT(fn,a,-);
for (int i=; i<=n; ++i)
F[i]+=a[i].x; for (int i=m; i<=n; ++i) if ((int)(F[i]+0.5)==) ans[++ans_num]=i-m+;
printf("%d\n",ans_num);
for (int i=; i<ans_num; ++i) printf("%d ",ans[i]);
printf("%d",ans[ans_num]);
}

最新文章

  1. WEB安全:XSS漏洞与SQL注入漏洞介绍及解决方案
  2. for...in也反复执行语句,但它是用来操作对象的
  3. 深入浅出设计模式——建造者模式(Builder Pattern)
  4. Ubuntu 安装JDK并配置成为默认的JDK
  5. [办公自动化]如何对Excel表格顶部设计
  6. Node.js 事件循环(Event Loop)介绍
  7. 7.cadence原理图后续[原创]
  8. C#基本数据类型
  9. cimge 这次能够图片大小尺寸
  10. 深入理解C++中的explicitkeyword
  11. mysql5.5 对触发器,函数,存储引擎,事件进行主从复制情况.(转)
  12. 六行代码获取本地IP
  13. PHP批量下载方法
  14. Servlet 笔记-servlet实例
  15. Android 优化APP 构建速度的17条建议
  16. hihocoder 1249(2015ACM/ICPC北京)
  17. (详细)华为荣耀V10 BKL-AL00的USB调试模式在哪里打开的步骤
  18. js通过查看屏幕大小,更改其他css属性
  19. CentOS 6.5环境下使用HAProxy+apache实现web服务的动静分离
  20. python常见面试题(mark)

热门文章

  1. saas模式
  2. WPF绑定之索引器值变化通知
  3. SpringBoot(六) Web Applications: Embedded Containers(嵌入式容器)
  4. servlet(一):从Sevlet到HttpServlet
  5. hdu 3295 模拟过程。数据很水
  6. github 上如何直接预览仓库中的html,搭建自己的主页
  7. 【1】Singleton模式(单例模式)
  8. Spring Hibernate JPA 联表查询 复杂查询
  9. Django中间件解析
  10. RSA与ECC的比较