https://www.lydsy.com/JudgeOnline/problem.php?id=4259

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

跟随胡神犇的步伐先把前置技能学了。

参考:https://www.cnblogs.com/clrs97/p/4814499.html

kmp是不行的,而作为一道套路题,我们有一定的套路:暴力匹配!

先默认字符串是以0开头的,方便我们后来FFT。

设dis(A,B)=(A-B)*[A!='*']*[B!='*']表示了AB字符是否相等,如果相等则答案为0。

于是我们把*字符看做0,则直接变成dis(A,B)=(A-B)AB。

设f[i]为B串以i为终点,往前与A匹配是否能匹配上。

显然就是dis累加的过程,只要最终f[i]=0就说明i-n+2是一个合法解。

然后你就会发现这个dis累加拆开之后很像卷积啊。

于是把A数组倒过来然后后面补齐0(即*字符),你就会发现实际上这就是三个卷积。

于是我们(不)愉快的写了个FFT并且AC。

(式子推导就看参考吧……心情不好不想写数学公式)

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef double dl;
const dl pi=acos(-1.0);
const dl eps=0.5;
const int N=2e6+;
struct complex{
dl x,y;
complex(dl xx=0.0,dl yy=0.0){
x=xx;y=yy;
}
complex operator +(const complex &b)const{
return complex(x+b.x,y+b.y);
}
complex operator -(const complex &b)const{
return complex(x-b.x,y-b.y);
}
complex operator *(const complex &b)const{
return complex(x*b.x-y*b.y,x*b.y+y*b.x);
}
};
void FFT(complex a[],int n,int on){
for(int i=,j=n>>;i<n-;i++){
if(i<j)swap(a[i],a[j]);
int k=n>>;
while(j>=k){j-=k;k>>=;}
if(j<k)j+=k;
}
for(int i=;i<=n;i<<=){
complex res(cos(-on**pi/i),sin(-on**pi/i));
for(int j=;j<n;j+=i){
complex w(,);
for(int k=j;k<j+i/;k++){
complex u=a[k],t=w*a[k+i/];
a[k]=u+t;a[k+i/]=u-t;
w=w*res;
}
}
}
if(on==-)
for(int i=;i<n;i++)a[i].x/=n;
}
int n,m,a[N],b[N];
complex f[N],A[N],B[N];
char s1[N],s2[N];
int main(){
scanf("%d%d%s%s",&n,&m,s1,s2);
for(int i=,j=n-;i<j;i++,j--)swap(s1[i],s1[j]);
for(int i=;i<n;i++){
if(s1[i]!='*')a[i]=s1[i]-'a'+;
else a[i]=;
}
for(int i=;i<m;i++){
if(s2[i]!='*')b[i]=s2[i]-'a'+;
else b[i]=;
}
int len=;
while(len<m)len<<=; for(int i=;i<len;i++)
A[i]=complex(a[i]*a[i]*a[i],),B[i]=complex(b[i],);
FFT(A,len,);FFT(B,len,);
for(int i=;i<len;i++)f[i]=f[i]+A[i]*B[i]; for(int i=;i<len;i++)
A[i]=complex(a[i]*a[i],),B[i]=complex(b[i]*b[i],);
FFT(A,len,);FFT(B,len,);
for(int i=;i<len;i++)f[i]=f[i]-A[i]*B[i]*complex(,); for(int i=;i<len;i++)
A[i]=complex(a[i],),B[i]=complex(b[i]*b[i]*b[i],);
FFT(A,len,);FFT(B,len,);
for(int i=;i<len;i++)f[i]=f[i]+A[i]*B[i]; FFT(f,len,-);
int ans=;
for(int i=n-;i<m;i++)if(f[i].x<eps)ans++;
printf("%d\n",ans);
if(ans){
for(int i=n-;i<m;i++)if(f[i].x<eps)printf("%d ",i-n+);
puts("");
}
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

最新文章

  1. Linux学习笔记(17) Shell编程之基础
  2. Ubuntu学习总结-09 安装 Pycharm
  3. 小白的vue学习路程
  4. Meet Python: little notes
  5. 文科生也能看懂的iptables教程(转载)
  6. VMware 安装CentOS
  7. 2016 - 1 -19 初探NSOperation
  8. Visual Studio 2013 各版本注册码
  9. sip比较好的博客
  10. poj1190生日蛋糕
  11. [改善Java代码]使用匿名类的构造函数
  12. 【HDOJ】2242 考研路茫茫——空调教室
  13. poj 2449 Remmarguts&amp;#39; Date 【SPFA+Astar】【古典】
  14. java基础之IO篇
  15. Floor报错原理分析
  16. 最长共公子序列(LCS)
  17. C#中得到程序当前工作目录和执行目录的五种方法
  18. vivado 创建PS工程
  19. python实现Content-Type类型为application/x-www-form-urlencoded发送POST请求
  20. [转载]WebService使用的一些总结

热门文章

  1. connect by 语句
  2. Selenium(Python) ddt读取CSV文件数据驱动
  3. es6笔记4^_^function
  4. 搭建hexo博客并部署到github上
  5. UVa 340 - Master-Mind Hints 解题报告 - C语言
  6. pandas协助工具
  7. 软件测试基础-Homework1
  8. Java学习个人备忘录之抽象类
  9. how to install pygraphviz on windows 10 with python 3.6
  10. 什么是BCL