zoukankan      html  css  js  c++  java
  • luogu4173 残缺的字符串

    对于一类带有通配符的字符串匹配问题,我们考虑构造匹配函数,通过匹配函数的值来判断匹配的位置。

    先考虑一个不带通配符的问题:给定两个字符串(A,B),判断(B)的哪些位置能与(A)匹配。

    除了kmp,我们同样可以考虑构造匹配函数来解决匹配问题,首先将(A)串翻转同时在其末尾补(0),构造函数(f_i=sum_{j=0}^i(A_j-B_{i-j})^2),那么(B)中在第(i)个位置结尾的长度为(|A|)的子串能与(A)匹配当且仅当(f_i=0)。将函数展开后得到(sum_{j=0}^i(A_j^2-2A_jB_{i-j}+B_{i-j}^2)),只需要一次FFT便能得到结果。

    现在考虑有通配符的情况,那么原来对匹配函数的定义显然是不完备的,考虑第(i)位有通配符时直接算作匹配,故可以在第(i)位为通配符时令(A_i=0),那么便可将匹配函数的定义完善为(f_i=sum_{j=0}^i(A_j-B_{i-j})^2A_jB_{i-j}).

    展开后得到(f_i=sum_{j=0}^i(A_j^3B_{i-j}-2A_j^2B_{i-j}^2+A_jB_{i-j}^3)).

    做三次多项式乘法即可。

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<bitset>
    #include<math.h>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef long double db;
    typedef pair<int,int> pii;
    const int N=300000+100;
    const db pi=acos(-1.0);
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define go(u,i) for (register int i=head[u];i;i=sq[i].nxt)
    #define fir first
    #define sec second
    #define mp make_pair
    #define pb push_back
    #define maxd 998244353
    #define eps 1e-8
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    namespace My_Math{
    	#define N 100000
    
    	int fac[N+100],invfac[N+100];
    
    	int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
    	int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
    	int mul(int x,int y) {return 1ll*x*y%maxd;}
    	ll qpow(ll x,int y)
    	{
    		ll ans=1;
    		while (y)
    		{
    			if (y&1) ans=mul(ans,x);
    			x=mul(x,x);y>>=1;
    		}
    		return ans;
    	}
    	int inv(int x) {return qpow(x,maxd-2);}
    
    	int math_init()
    	{
    		fac[0]=invfac[0]=1;
    		rep(i,1,N) fac[i]=mul(fac[i-1],i);
    		invfac[N]=inv(fac[N]);
    		per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
    	}
    	#undef N
    }
    using namespace My_Math;
    
    namespace polynomial{
    	struct complex{
    		double x,y;
    		complex (double _x=0.0,double _y=0.0) {x=_x;y=_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);}
    	complex operator *(complex a,complex b) {return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
    	
    	int r[N<<2];
    	void calcr(int &lim,int len)
    	{
    		lim=1;int cnt=0;
    		while (lim<len) {lim<<=1;cnt++;}
    		rep(i,0,lim-1) 
    			r[i]=(r[i>>1]>>1)|((i&1)<<(cnt-1));
    	}
    	
    	void fft(int lim,complex *a,int typ)
    	{
    		rep(i,0,lim-1)
    			if (i<r[i]) swap(a[i],a[r[i]]);
    		for (int mid=1;mid<lim;mid<<=1)
    		{
    			complex wn=complex(cos(pi/mid),sin(pi/mid)*typ);
    			int len=(mid<<1);
    			for (int sta=0;sta<lim;sta+=len)
    			{
    				complex w=complex(1,0);
    				for (int j=0;j<mid;j++,w=w*wn)
    				{
    					complex x=a[j+sta],y=a[j+sta+mid]*w;
    					a[j+sta]=x+y;a[j+sta+mid]=x-y;
    				}
    			}
    		}
    		if (typ==-1)
    			rep(i,0,lim-1) a[i].x/=lim;
    	}
    }
    using namespace polynomial;
    complex A[N<<2],B[N<<2],C[N<<2],emp=complex(0,0);
    int a[N],b[N],n,m;
    char s[N];
    vector<int> ans;
    
    int main()
    {
    	n=read();m=read();
    	scanf("%s",s);
    	rep(i,0,n-1) 
    		if (s[i]!='*') a[i]=s[i]-'a'+1;
    	reverse(a,a+n);
    	scanf("%s",s);
    	rep(i,0,m-1) 
    		if (s[i]!='*') b[i]=s[i]-'a'+1;
    	int lim=0;
    	calcr(lim,m*2);
    	rep(i,0,n-1) A[i]=complex(a[i]*a[i]*a[i],0);
    	rep(i,0,m-1) B[i]=complex(b[i],0);
    	fft(lim,A,1);fft(lim,B,1);
    	rep(i,0,lim-1) C[i]=C[i]+A[i]*B[i];
    	rep(i,0,lim-1) A[i]=B[i]=emp;
    	rep(i,0,n-1) A[i]=complex(a[i]*a[i],0);
    	rep(i,0,m-1) B[i]=complex(b[i]*b[i],0);
    	fft(lim,A,1);fft(lim,B,1);
    	rep(i,0,lim-1) C[i]=C[i]-A[i]*B[i]*2;
    	rep(i,0,lim-1) A[i]=B[i]=emp;
    	rep(i,0,n-1) A[i]=complex(a[i],0);
    	rep(i,0,m-1) B[i]=complex(b[i]*b[i]*b[i],0);
    	fft(lim,A,1);fft(lim,B,1);
    	rep(i,0,lim-1) C[i]=C[i]+A[i]*B[i];
    	fft(lim,C,-1);
    	rep(i,n-1,m-1)
    		if (fabs(C[i].x)+0.5<1) ans.pb(i-n+2);
    	int len=ans.size();
    	printf("%d
    ",len);
    	rep(i,0,len-1) printf("%d ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Apache Ant 1.9.1 版发布
    Apache Subversion 1.8.0rc2 发布
    GNU Gatekeeper 3.3 发布,网关守护管理
    Jekyll 1.0 发布,Ruby 的静态网站生成器
    R语言 3.0.1 源码已经提交到 Github
    SymmetricDS 3.4.0 发布,数据同步和复制
    beego 0.6.0 版本发布,Go 应用框架
    Doxygen 1.8.4 发布,文档生成工具
    SunshineCRM 20130518发布,附带更新说明
    Semplice Linux 4 发布,轻量级发行版
  • 原文地址:https://www.cnblogs.com/encodetalker/p/12387381.html
Copyright © 2011-2022 走看看