BZOJ 4259: 残缺的字符串 [FFT]

4259: 残缺的字符串

题意:s,t,星号任意字符,匹配方案数


和上题一样
多乘上一个\(a_{j+i}\)就行了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=(1<<20)+5;
const double PI=acos(-1);
inline int read(){
	char c=getchar();int x=0,f=1;
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return x*f;
}
 
struct meow{
	double x, y;
	meow(double a=0, double b=0):x(a), y(b){}
};
meow operator +(meow a, meow b) {return meow(a.x+b.x, a.y+b.y);}
meow operator -(meow a, meow b) {return meow(a.x-b.x, a.y-b.y);}
meow operator *(meow a, meow b) {return meow(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x);}
meow conj(meow a) {return meow(a.x, -a.y);}
typedef meow cd;
 
namespace FFT{
	int n, rev[N];
	void ini(int lim) {
		n=1; int k=0;
		while(n<lim) n<<=1, k++;
		for(int i=0; i<n; i++) rev[i] = (rev[i>>1]>>1) | ((i&1)<<(k-1));
	}
	void dft(cd *a, int flag) {
		for(int i=0; i<n; i++) if(i<rev[i]) swap(a[i], a[rev[i]]);
		for(int l=2; l<=n; l<<=1) {
			int m=l>>1; 
			cd wn = meow(cos(2*PI/l), flag*sin(2*PI/l));
			for(cd *p=a; p!=a+n; p+=l) {
				cd w(1, 0);
				for(int k=0; k<m; k++) {
					cd t = w*p[k+m];
					p[k+m] = p[k] - t;
					p[k] = p[k] + t;
					w=w*wn;
				}
			}
		}
		if(flag==-1) for(int i=0; i<n; i++) a[i].x/=n;
	}
}using FFT::dft; using FFT::ini;
 
int n, m, lim;
cd a[N], b[N], a2[N], b2[N], a3[N], b3[N], c[N];
char s[N], t[N];
int ans, li[N];
int main() {
	freopen("in","r",stdin);
	m=read(); n=read(); lim=n+m-1; ini(lim);
	scanf("%s%s",t,s);
	for(int i=0; i<n; i++) s[i]= s[i]=='*' ? 0 : s[i]-'a'+1;
	for(int i=0; i<m; i++) t[i]= t[i]=='*' ? 0 : t[i]-'a'+1;
 
	for(int i=0; i<n; i++) a[i].x = s[i], a2[i].x = 2*s[i]*s[i], a3[i].x = s[i]*s[i]*s[i];
	for(int i=0; i<m; i++) b[m-1-i].x = t[i], b2[m-1-i].x = t[i]*t[i], b3[m-1-i].x = t[i]*t[i]*t[i];
	 
	dft(a, 1); dft(a2, 1); dft(a3, 1); dft(b, 1); dft(b2, 1); dft(b3, 1);
	for(int i=0; i<FFT::n; i++) c[i] = a3[i]*b[i] - a2[i]*b2[i] + a[i]*b3[i];
	dft(c, -1);
	for(int i=0; i<=n-m; i++) if(floor(c[m-1+i].x+0.5)==0) li[++ans]=i;
	printf("%d\n",ans);
	for(int i=1; i<=ans; i++) printf("%d ",li[i]+1);
}
posted @ 2017-03-30 21:48  Candy?  阅读(295)  评论(0编辑  收藏  举报