1 条题解

  • 0
    @ 2024-10-20 20:15:43

    题解:

    对每种字符单独考虑。

    对于字符cc,首先除去SSTT中非cc字符,例如S=ABABABABCABCABCS=ABABABABCABCABCT=CBAAT=CBAAc=Ac='A',处理后S=A#A#A#A##A##A##S=A\#A\#A\#A\#\#A\#\#A\#\#T=##AAT=\#\#AA。对于kk,可以将SS中的字母cc向两边扩散kk。例如当k=3k=3,此时S=AAAAAAAAAAAAAAAS=AAAAAAAAAAAAAAA

    考虑成功匹配时,SS上的每个字符,与TT上的的对应字符,位置的差是相等,将其中一个串反转,则匹配字符位置和相同,可以拆成多项式卷积形式。的对于字符cc,构造 F(x)=i=0nxi[Si=c]F(x)=∑^n_{i=0}x^i[S_i=c],将 TT 串翻转操作后,G(x)=i=0nxi[Ti=c]G(x)=∑^n_{i=0}x^i[T_i=c],若从SSii位开始SSTT能匹配,则F(x)G(x)F(x)*G(x)xix^i 项的系数应为TTcc的数量。累加每种字符对应的F(x)G(x)F(x)*G(x),若xix^i项的系数为T|T|,则该位置可以匹配。

    struct Polynomial{
    	const double PI=std::acos(-1.0);
    	struct Complex{
    		double x,y;
    		Complex(double _x=0.0,double _y=0.0){
    			x=_x;y=_y;
    		}
    		Complex operator-(const Complex &rhs)const{
    			return Complex(x-rhs.x,y-rhs.y);
    		}
    		Complex operator+(const Complex &rhs)const{
    			return Complex(x+rhs.x,y+rhs.y);
    		}
    		Complex operator*(const Complex &rhs)const{
    			return Complex(x*rhs.x-y*rhs.y,x*rhs.y+y*rhs.x);
    		}
    	};
    	int n;
    	std::vector<Complex> c;
    	Polynomial(int coef){
    		int len=1<<(int)std::ceil(std::log2(coef+1));
    		this->n=len;
    		c.resize(len);
    	}
    	void modify(int pos,int val){c[pos]=Complex(val,0);}
    	void change(std::vector<Complex> &y,int len){
    		for(int i=1,j=len/2;i<len-1;i++){
    			if(i<j)std::swap(y[i],y[j]);
    			int k=len/2;
    			while(j>=k){
    				j-=k;
    				k/=2;
    			}
    			if(j<k)j+=k;
    		}
    	}
    	void fft(std::vector<Complex> &y,int len,int opt){
    		change(y,len);
    		for(int h=2;h<=n;h<<=1){
    			Complex wn(cos(2.0*PI/h),sin(2.0*PI*opt/h));
    			for(int j=0;j<len;j+=h){
    				Complex w(1,0);
    				for(int k=j;k<j+h/2;k++){
    					Complex u=y[k];
    					Complex t=w*y[k+h/2];
    					y[k]=u+t;
    					y[k+h/2]=u-t;
    					w=w*wn;
    				}
    			}
    		}
    		if(opt==-1){
    			for(int i=0;i<len;i++)y[i].x/=len;
    		}
    	}
    	void mul(Polynomial b){
        	fft(c,n,1);
        	fft(b.c,b.n,1);
        	for(int i=0;i<n;i++)c[i]=c[i]*b.c[i];
        	fft(c,n,-1);
        }	
    };
    void solve(){
    	int n,m,k;
    	std::string s,t;
    	std::cin>>n>>m>>k>>s>>t;
    	std::set<char> S;
    	for(auto c:s)S.insert(c);
    	for(auto c:t)S.insert(c);
    	std::vector<int> cnt(n+m-1);
    	auto cal=[&](char c){
    		Polynomial f(n+m-2),g(n+m-2);
    		for(int i=0,lst=-k-1;i<n;i++){
    			if(s[i]==c)lst=i;
    			if(i-lst<=k)f.modify(i,1);
    		}
    		for(int i=n-1,lst=n+k;i>=0;i--){
    			if(s[i]==c)lst=i;
    			if(lst-i<=k)f.modify(i,1);
    		}
    		for(int i=0;i<m;i++)g.modify(i,(t[m-1-i]==c));
    		f.mul(g);
    		for(int i=0;i<n;i++)cnt[i]+=std::round(f.c[i].x);
    	};
    	for(auto c:S)cal(c);
    	int ans=0;
    	for(int i=0;i<n;i++)ans+=(cnt[i]==m);
    	std::cout<<ans<<'\n';
    }
    
    • 1

    信息

    ID
    212
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    325
    已通过
    5
    上传者