zoukankan      html  css  js  c++  java
  • 【2018牛客多校round3 D】Encrypted String Matching

    题意

    凯撒密码的映射规则是
    给你一个加密表book[26](26个字母的排列)
    原字符是a,加密后的字符是book[a-'a']
    现在加密会出现问题,可能会相差1位,比如加密后是b,可能会显示a和c,解密是正常的
    Alice将字符串T加密后E(T)发给Bob,Bob将这个字符串解密D(E(T))得到字符串S,问S和T在有误差的情况下是否相等

    分析

    考虑到加密和解密是一个相反操作
    判断 D(E(T)) == T相当于 判断E(T) == E(S)
    D操作是正确的,所以S的加密也是正确的
    所以就是T串的值可能会有1的误差
    这里类似于BZOJ4503
    我们需要构造一个表达式,来表示S串中一位和T串中一位是不是有误差的相等
    F(s,t) = (s-t)2*((s-t)2-1) = (s-t)^4 - (s-t)^2 这样当s == t 或者s == t-1 或者 s == t+1 时 F(s,t)==0,否则 F(s,t)>0
    如果要整个连续的字符串都是相等的,那么就是∑F(s_i,t_j) == 0 ( j-i == k ) 为一个常数
    将t串反向后,展开表达式满足卷积性质
    所以求一个卷积就好了,其中为0的元素则是匹配位置

    代码

    #include<bits/stdc++.h>
    using namespace std;
    long long f[7][500005],g[7][500005],n_f,n_g;
    char s1[250005],s2[250005],dic[30];
    long long en[30],de[30],s[500005];
    const double pi = acos(-1);
    const double pi_2 = 2*pi;
      
    struct Complex // 复数
    {
        double r,i;
        Complex(double _r = 0, double _i = 0) :r(_r), i(_i) {}
        Complex operator +(const Complex &b) {
            return Complex(r + b.r, i + b.i);
        }
        Complex operator -(const Complex &b) {
            return Complex(r - b.r, i - b.i);
        }
        Complex operator *(const Complex &b) {
            return Complex(r*b.r - i*b.i, r*b.i + i*b.r);
        }
    }xf[1000005],xg[1000005];
     
     
     
    void change(Complex y[],int len){
        int i,j,k;
        for(i=1,j=len/2;i<len-1;++i){
            if(i<j)swap(y[i],y[j]);
            k=len>>1;
            for(;j>=k;j-=k,k>>=1);
            if(j<k)j+=k;
        }
    }
    void fft(Complex y[],int len,int on){
        change(y,len);
        for(int h=2;h<=len;h<<=1){
            Complex wn(cos(-on*pi_2/h),sin(-on*pi_2/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],t=w*y[k+h/2];
                    y[k]=u+t;
                    y[k+h/2]=u-t;
                    w=w*wn;
                }
            }
        }
        if(on==-1)
        for(int i=0;i<len;++i)
        y[i].r/=len;
    }
     
    void debug()
    {
    long long k = n_f+ n_g-n_f-3 -1;
        for(long long i = n_g-n_f,j=1;i>=0;i--,j++)
        {
        long long k = n_f+i-1;
        cout<<j<<"::"<<(long long)(xf[k].r+0.5)<<endl;
        }
        cout<<s[k]<<endl;
        cout<<endl;
    }
      
    int  main()
    {
        scanf("%s%s%s",s1,s2,dic);
        for(long long i =0 ;i<26;i++){
        en[i] = dic[i]-'a';
        de[dic[i]-'a'] = i;
        }
        n_f = strlen(s1);n_g = strlen(s2);
        for(long long i = 0;i<n_f;i++) {
        f[0][i] = 1LL;f[1][i] = en[s1[i]-'a'];
        for(long long j = 2;j<=6;j++) f[j][i] = f[j-1][i]*f[1][i];
      
        }  
        for(long long i = 0;i<n_g;i++)
        {
        g[0][n_g-i-1] = 1LL;g[1][n_g-i-1] = en[s2[i]-'a'];
        for(long long j=2;j<=6;j++) g[j][n_g-i-1] =  g[j-1][n_g-i-1] * g[1][n_g-i-1];
        }
          
      
      
      
    //    for(long long i = 0;i<n_f;i++) cout<<f[1][i]<<" ";
     // cout<<endl;
     //   for(long long i = 0;i<n_g;i++) cout<<g[1][i]<<" ";
     //   cout<<endl;
          
          
          
          
        long long n = n_f+n_g+1;
        long long len = 1;
        while(len < n)len <<=1;
      
        for(long long i = 0;i<n;i++) xf[i] = Complex(f[4][i],0),xg[i] = Complex(g[0][i],0);
        for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
        fft(xf,len,1);fft(xg,len,1);
        for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
        fft(xf,len,-1);
        for(long long i=0;i<=n_g-n_f;i++){
        long long k = n_f+i-1;
        s[k]+=(long long)(xf[k].r+0.5);
        }
      
        for(long long i = 0;i<n;i++) xf[i] = Complex(f[0][i],0),xg[i] = Complex(g[4][i],0);
        for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
        fft(xf,len,1);fft(xg,len,1);
        for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
        fft(xf,len,-1);
        for(long long i=0;i<=n_g-n_f;i++){
        long long k = n_f+i-1;
        s[k]+=(long long)(xf[k].r+0.5);
        }
      
      
        for(long long i = 0;i<n;i++) xf[i] = Complex(f[3][i],0),xg[i] = Complex(g[1][i],0);
        for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
        fft(xf,len,1);fft(xg,len,1);
        for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
        fft(xf,len,-1);
        for(long long i=0;i<=n_g-n_f;i++){
        long long k = n_f+i-1;
        s[k]-=4*(long long)(xf[k].r+0.5);
        }
      
      
      
        for(long long i = 0;i<n;i++) xf[i] = Complex(f[1][i],0),xg[i] = Complex(g[3][i],0);
        for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
        fft(xf,len,1);fft(xg,len,1);
        for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
        fft(xf,len,-1);
        for(long long i=0;i<=n_g-n_f;i++){
        long long k = n_f+i-1;
        s[k]-=4*(long long)(xf[k].r+0.5);
        }
      
      
      
        for(long long i = 0;i<n;i++) xf[i] = Complex(f[2][i],0),xg[i] = Complex(g[2][i],0);
        for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
        fft(xf,len,1);fft(xg,len,1);
        for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
        fft(xf,len,-1);
        for(long long i=0;i<=n_g-n_f;i++){
        long long k = n_f+i-1;
        s[k]+=6*(long long)(xf[k].r+0.5);
        }
      
      
      
      
        for(long long i = 0;i<n;i++) xf[i] = Complex(f[2][i],0),xg[i] = Complex(g[0][i],0);
        for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
        fft(xf,len,1);fft(xg,len,1);
        for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
        fft(xf,len,-1);
        for(long long i=0;i<=n_g-n_f;i++){
        long long k = n_f+i-1;
        s[k]-=(long long)(xf[k].r+0.5);
        }
      
      
      
        for(long long i = 0;i<n;i++) xf[i] = Complex(f[0][i],0),xg[i] = Complex(g[2][i],0);
        for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
        fft(xf,len,1);fft(xg,len,1);
        for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
        fft(xf,len,-1);
        for(long long i=0;i<=n_g-n_f;i++){
        long long k = n_f+i-1;
        s[k]-=(long long)(xf[k].r+0.5);
        }
      
        for(long long i = 0;i<n;i++) xf[i] = Complex(f[1][i],0),xg[i] = Complex(g[1][i],0);
        for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
        fft(xf,len,1);fft(xg,len,1);
        for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
        fft(xf,len,-1);
        for(long long i=0;i<=n_g-n_f;i++){
        long long k = n_f+i-1;
        s[k]+=2*(long long)(xf[k].r+0.5);
        }
      
      
      
        vector<long long>ans;
        for(long long i = n_g-n_f,j=1;i>=0;i--,j++)
        {
        long long k = n_f+i-1;
    //  cout<<j<<"::"<<s[k]<<endl;
        if(s[k] == 0) ans.push_back(j);
        }
      //  cout<<endl;
        int nn = ans.size();
        printf("%d",nn);
        if(nn)
        {
        puts("");
            for(long long i =0 ;i<nn;i++)
        {
            printf("%lld ",ans[i]);
        }
        }
       }
    
  • 相关阅读:
    1208C Magic Grid
    jsc2019_qualE Card Collector
    jsc2019_qualD Classified
    jsc2019_qualC Cell Inversion
    牛客提高D6t3 分班问题
    牛客提高D6t2 破碎的序列
    牛客提高D6t1 积木大赛
    loj6259「CodePlus 2017 12 月赛」白金元首与独舞
    p4208 [JSOI2008]最小生成树计数
    p4111 [HEOI2015]小Z的房间[简述矩阵树定理]
  • 原文地址:https://www.cnblogs.com/greenty1208/p/9379440.html
Copyright © 2011-2022 走看看