【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]);
    }
    }
   }
posted @ 2018-07-27 20:00  Greenty  阅读(123)  评论(0编辑  收藏  举报