zoukankan      html  css  js  c++  java
  • 【刷题】BZOJ 4259 残缺的字符串

    Description

    很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n。可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺。

    你想对这两个串重新进行匹配,其中A为模板串,那么现在问题来了,请回答,对于B的每一个位置i,从这个位置开始连续m个字符形成的子串是否可能与A串完全匹配?

    Input

    第一行包含两个正整数m,n(1<=m<=n<=300000),分别表示A串和B串的长度。

    第二行为一个长度为m的字符串A。

    第三行为一个长度为n的字符串B。

    两个串均仅由小写字母和号组成,其中号表示相应位置已经残缺。

    Output

    第一行包含一个整数k,表示B串中可以完全匹配A串的位置个数。

    若k>0,则第二行输出k个正整数,从小到大依次输出每个可以匹配的开头位置(下标从1开始)。

    Sample Input

    3 7
    a*b
    aebr*ob

    Sample Output

    2
    1 5

    Solution

    这就是BZOJ 4503 两个串的升级版
    思路可以看那篇
    这题的式子相较就只改变成 (f(i)=sum_{j=0}^ix_{i-j}^3y_j-2x_{i-j}^2y_j^2+x_{i-j}y_j^3)
    变成了3个卷积
    一样用FFT求解就好了

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=1<<20;
    const db Pi=acos(-1.0);
    int n1,n2,n,m,cnt,rev[MAXN],ans[MAXN],nt;
    char s1[MAXN],s2[MAXN];
    struct Complex{
    	db real,imag;
    	inline Complex operator + (const Complex &A) const {
    		return (Complex){real+A.real,imag+A.imag};
    	};
    	inline Complex operator - (const Complex &A) const {
    		return (Complex){real-A.real,imag-A.imag};
    	};
    	inline Complex operator * (const Complex &A) const {
    		return (Complex){real*A.real-imag*A.imag,imag*A.real+real*A.imag};
    	};
    };
    Complex x[MAXN],x2[MAXN],x3[MAXN],y[MAXN],y2[MAXN],y3[MAXN];
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline void FFT(Complex *A,int tp)
    {
    	for(register int i=0;i<n;++i)
    		if(i<rev[i])std::swap(A[i],A[rev[i]]);
    	for(register int l=2;l<=n;l<<=1)
    	{
    		Complex wn=(Complex){cos(2*Pi/l),sin(tp*2*Pi/l)};
    		for(register int i=0;i<n;i+=l)
    		{
    			Complex w=(Complex){1,0};
    			for(register int j=0;j<(l>>1);++j)
    			{
    				Complex A1=A[i+j],A2=w*A[i+j+(l>>1)];
    				A[i+j]=A1+A2,A[i+j+(l>>1)]=A1-A2;
    				w=w*wn;
    			}
    		}
    	}
    }
    int main()
    {
    	read(n1);read(n2);
    	m=n1+n2-1;
    	scanf("%s",s1);scanf("%s",s2);
    	for(register int i=0;i<n1;++i)
    	{
    		x[n1-i-1].real=(s1[i]=='*'?0:s1[i]-'a'+1);
    		x2[n1-i-1].real=x[n1-i-1].real*x[n1-i-1].real*2;
    		x3[n1-i-1].real=x[n1-i-1].real*x[n1-i-1].real*x[n1-i-1].real;
    	}
    	for(register int i=0;i<n2;++i)
    	{
    		y[i].real=(s2[i]=='*'?0:s2[i]-'a'+1);
    		y2[i].real=y[i].real*y[i].real;
    		y3[i].real=y[i].real*y[i].real*y[i].real;
    	}
    	for(n=1;n<m;n<<=1)++cnt;
    	for(register int i=0;i<n;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
    	FFT(x,1);FFT(x2,1);FFT(x3,1);
    	FFT(y,1);FFT(y2,1);FFT(y3,1);
    	for(register int i=0;i<n;++i)x[i]=x3[i]*y[i]-x2[i]*y2[i]+x[i]*y3[i];
    	FFT(x,-1);
    	for(register int i=0;i<n2-n1+1;++i)
    		if((int)(x[n1+i-1].real/n+0.5)==0)ans[++nt]=i;
    	write(nt,'
    ');
    	for(register int i=1;i<=nt;++i)write(ans[i]+1,' ');
    	puts("");
    	return 0;
    }
    
  • 相关阅读:
    说一下Mysql索引
    B树、B-树、B+树、B*树之间的关系
    Mybatis Plus 的优点
    JVM垃圾回收机制
    Java中的集合
    MQ 面试题
    Redis 双写一致性
    Redis 主从复制
    C#中Abstract和Virtual的区别
    C#设计模式(2)——简单工厂模式
  • 原文地址:https://www.cnblogs.com/hongyj/p/9179666.html
Copyright © 2011-2022 走看看