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

    传送门

    两种做法,一种是依次考虑每种字符,然后如果某个位置是该字符或者是(*)对应的值就是1,否则是0,然后把第一个串倒过来,fft卷积起来,最后看对应位置的值是否为m

    然而上面那个做法在字符集大小过大的时候会GG,所以考虑一次性匹配,如果不考虑通配符(*),设(开头)位置i的匹配函数为(f(i)=sum_{j=1}^{m}(a_j-b_{i+m-j})^2),(f(i)=0)说明i可以匹配

    因为通配符可以匹配任何字符,也就是会让某组匹配一定是0,那么(f(i))可以改成(f(i)=sum_{j=1}^{m}(a_j-b_{i+m-j})^2a_jb_{i+m-j}),化简得到(f(i)=sum_{j=1}^{m}{a_j}^3b_{i+m-j}+a_j{b_{i+m-j}}^3-2{a_j}^2{b_{i+m-j}}^2),然后三遍fft就好了

    然后我ntt被fft吊着打qwq

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    #define db double
    #define il inline
    #define re register
    
    using namespace std;
    const int N=(1<<20)+10,mod=998244353;
    il int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int rdr[N];
    il int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;} return an;}
    void ntt(int *a,int n,bool op)
    {
        int l=0,x,y;
        while((1<<l)<n) ++l;
        for(int i=0;i<n;++i) rdr[i]=(rdr[i>>1]>>1)|((i&1)<<(l-1));
        for(int i=0;i<n;++i) if(i<rdr[i]) swap(a[i],a[rdr[i]]);
        for(int i=1;i<n;i<<=1)
        {
            int ww=fpow(op?3:332748118,(mod-1)/(i<<1));
            for(int j=0;j<n;j+=i<<1)
                for(int k=0,w=1;k<i;++k,w=1ll*w*ww%mod)
                    x=a[j+k],y=1ll*a[j+k+i]*w%mod,a[j+k]=(x+y)%mod,a[j+k+i]=(x-y+mod)%mod;
        }
        if(!op) for(int i=0,w=fpow(n,mod-2);i<n;++i) a[i]=1ll*a[i]*w%mod;
    }
    int n,m,hh[N],a[N],b[N],an[N],ta;
    char cc[N],ss[N];
    
    int main()
    {
        n=rd(),m=rd();
        int l=1;
        while(l<=n+m) l<<=1;
        scanf("%s%s",cc,ss);
        for(int i=0;i<n;++i)
        {
            int x=cc[n-i-1]=='*'?0:cc[n-i-1]-96;
            a[i]=x*x*x;
        }
        for(int i=0;i<m;++i)
        {
            int x=ss[i]=='*'?0:ss[i]-96;
            b[i]=x;
        }
        ntt(a,l,1),ntt(b,l,1);
        for(int i=0;i<l;++i) a[i]=1ll*a[i]*b[i]%mod;
        ntt(a,l,0);
        for(int i=1;i<=m;++i) hh[i]=(hh[i]+a[n+i-2])%mod;
        for(int i=0;i<l;++i) a[i]=b[i]=0;
        for(int i=0;i<n;++i)
        {
            int x=cc[n-i-1]=='*'?0:cc[n-i-1]-96;
            a[i]=x;
        }
        for(int i=0;i<m;++i)
        {
            int x=ss[i]=='*'?0:ss[i]-96;
            b[i]=x*x*x;
        }
        ntt(a,l,1),ntt(b,l,1);
        for(int i=0;i<l;++i) a[i]=1ll*a[i]*b[i]%mod;
        ntt(a,l,0);
        for(int i=1;i<=m;++i) hh[i]=(hh[i]+a[n+i-2])%mod;
        for(int i=0;i<l;++i) a[i]=b[i]=0;
        for(int i=0;i<n;++i)
        {
            int x=cc[n-i-1]=='*'?0:cc[n-i-1]-96;
            a[i]=x*x;
        }
        for(int i=0;i<m;++i)
        {
            int x=ss[i]=='*'?0:ss[i]-96;
            b[i]=x*x;
        }
        ntt(a,l,1),ntt(b,l,1);
        for(int i=0;i<l;++i) a[i]=1ll*a[i]*b[i]%mod;
        ntt(a,l,0);
        for(int i=1;i<=m;++i) hh[i]=((hh[i]-a[n+i-2]-a[n+i-2])%mod+mod)%mod;
        for(int i=0;i<l;++i) a[i]=b[i]=0;
        for(int i=1;i<=m-n+1;++i)
            if(!hh[i]) an[++ta]=i;
        printf("%d
    ",ta);
        for(int i=1;i<=ta;++i) printf("%d ",an[i]);
        return 0;
    }
    
  • 相关阅读:
    kettle的使用(ETL,数据仓库技术)
    最近工作用到压缩,写一个zip压缩工具类
    JAVA 7新特性——在单个catch代码块中捕获多个异常,以及用升级版的类型检查重新抛出异常
    JAVA反射机制
    guava的使用
    web项目中无法开启或404
    关于request.getServletContext()方法报错的问题
    使用U盘给笔记本重做系统
    sed速查手册
    awk速查手册
  • 原文地址:https://www.cnblogs.com/smyjr/p/10448215.html
Copyright © 2011-2022 走看看