fft应用于字符串匹配模板

题目链接:https://www.luogu.com.cn/problem/P4173

在这里插入图片描述

代码
#include<bits/stdc++.h>
#define MAXN 2000005
#define reg register
#define inl inline
#define db double
#define eps 1e-6
using namespace std;
const int Mod=998244353;
const db Pi=acos(-1.0);
struct Complex
{
	db x,y;
	friend Complex operator + (const Complex &a,const Complex &b)
	{
		return ((Complex){a.x+b.x,a.y+b.y});
	}
	friend Complex operator - (const Complex &a,const Complex &b)
	{
		return ((Complex){a.x-b.x,a.y-b.y});
	}
	friend Complex operator * (const Complex &a,const Complex &b)
	{
		return ((Complex){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x});
	}
	friend Complex operator * (const Complex &a,const db &val)
	{
		return ((Complex){a.x*val,a.y*val});
	}
}f[MAXN],g[MAXN],p[MAXN];
int n,m,lim=1,maxn,rev[MAXN],a[MAXN],b[MAXN];
char S[MAXN],T[MAXN];
bool used[MAXN];
vector <int> v;
inl void FFT(reg Complex *A,reg int opt)
{
	for(reg int i=0;i<lim;i++) if(i<rev[i]) swap(A[i],A[rev[i]]);
	for(reg int mid=1;mid<lim;mid<<=1)
	{
		reg Complex Wn=((Complex){cos(Pi/(db)mid),(db)opt*sin(Pi/(db)mid)});
		for(reg int j=0;j<lim;j+=(mid<<1))
		{
			reg Complex W=((Complex){1,0});
			for(reg int k=0;k<mid;k++,W=W*Wn)
			{
				reg Complex x=A[j+k],y=W*A[j+k+mid];
				A[j+k]=x+y;
				A[j+k+mid]=x-y;
			}
		}
	}
}
int main()
{
	scanf("%d %d",&m,&n);
	scanf("%s",T+1);
	scanf("%s",S+1);
	for(reg int i=1;i<=m;i++) if(T[i]!='*') a[i-1]=T[i]-'a'+1;
	for(reg int i=1;i<=n;i++) if(S[i]!='*') b[i-1]=S[i]-'a'+1;
	while(lim<=(n+m))
	{
		lim<<=1;
		maxn++;
	}
	for(reg int i=0;i<lim;i++) rev[i]=((rev[i>>1]>>1)|((i&1)<<maxn-1));
	reverse(a,a+m);
	for(reg int i=0;i<m;i++) f[i]=((Complex){a[i]*a[i]*a[i],0});
	for(reg int i=0;i<n;i++) g[i]=((Complex){b[i],0});
	FFT(f,1);FFT(g,1);
	for(reg int i=0;i<lim;i++) p[i]=p[i]+f[i]*g[i];
	for(reg int i=0;i<lim;i++) f[i]=g[i]=((Complex){0,0});
	for(reg int i=0;i<m;i++) f[i]=((Complex){a[i]*a[i],0});
	for(reg int i=0;i<n;i++) g[i]=((Complex){b[i]*b[i],0});
	FFT(f,1);FFT(g,1);
	for(reg int i=0;i<lim;i++) p[i]=p[i]-f[i]*g[i]*2.0;
	for(reg int i=0;i<lim;i++) f[i]=g[i]=((Complex){0,0});
	for(reg int i=0;i<m;i++) f[i]=((Complex){a[i],0});
	for(reg int i=0;i<n;i++) g[i]=((Complex){b[i]*b[i]*b[i],0});
	FFT(f,1);FFT(g,1);
	for(reg int i=0;i<lim;i++) p[i]=p[i]+f[i]*g[i];
	FFT(p,-1);
	for(reg int i=m-1;i<n;i++) if(!(int)(p[i].x/(db)lim+0.5)) v.push_back(i-m+2);
	reg int Ans=v.size();
	printf("%d\n",Ans);
	for(reg int i=0;i<Ans;i++) printf("%d ",v[i]);
	return 0;
}
无通配符情况
void FFT_Match(char *s1,char *s2,int m,int n)
{
	for(int i=0;i<m;i++) A[i].r=s1[i]-'a'+1;
	for(int i=0;i<n;i++) B[i].r=s2[i]-'a'+1;
	reverse(A,A+m);double T=0;
	for(int i=0;i<m;i++) T+=A[i].r*A[i].r;
	f[0]=B[0].r*B[0].r;
	for(int i=1;i<n;i++) f[i]=f[i-1]+B[i].r*B[i].r;
	FFT(A,len,1);FFT(B,len,1);
	for(int i=0;i<len;i++) g[i]=A[i]*B[i];
	FFT(g,len,-1);
	for(int x=m-1;x<n;x++)
	{
		double P=T+f[x]-f[x-m]-2*g[x].r;
		if(fabs(P)<eps) printf("%d ",x-m+2);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值