• CF954I Yet Another String Matching Problem ( FFT )


    Description

    给出两个字符串S和T
    定义两个等长的字符串A和B之间的距离为:
    每次操作可以选择两个字符c1和c2,将两个字符串中的所有c1替换为c2,这样将A和B变为相等的最小操作次数。
    求S的每个长度为|T|的子串和T之间的距离。
    n<=125000,保证S和T只含有小写字母a~f







    暴力的话,每个子串用并查集o (n) 的扫一遍的话复杂度是 s × t 的

    考虑如何优化

    题目的字符集之有6,所以可以考虑在每一块中,枚举的两个字符之间是否在对应位置匹配(这个可以FFT搞了)

    若果匹配的话的,再看在当前块内,这两个字符的fa是否是一个





     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<set>
     8 #include<map>
     9 #include<vector>
    10 #include<queue>
    11 using namespace std;
    12 #define ll long long
    13 #define RG register
    14 #define MAX 333333
    15 const double Pi=acos(-1);
    16 struct Complex{double a,b;}A[MAX],B[MAX],W[MAX];
    17 Complex operator+(Complex a,Complex b){return (Complex){a.a+b.a,a.b+b.b};}
    18 Complex operator-(Complex a,Complex b){return (Complex){a.a-b.a,a.b-b.b};}
    19 Complex operator*(Complex a,Complex b){return (Complex){a.a*b.a-a.b*b.b,a.a*b.b+a.b*b.a};}
    20 int r[MAX],N,n,m,l,eql[MAX][6][6];
    21 char a[MAX],b[MAX];
    22 void FFT(Complex *P,int opt)
    23 {
    24     for(int i=1;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
    25     for(int i=1;i<N;i<<=1)
    26         for(int p=i<<1,j=0;j<N;j+=p)
    27             for(int k=0;k<i;++k)
    28             {
    29                 Complex w=(Complex){W[N/i*k].a,W[N/i*k].b*opt};
    30                 Complex X=P[j+k],Y=w*P[i+j+k];
    31                 P[j+k]=X+Y;P[i+j+k]=X-Y;
    32             }
    33 }
    34 int f[6];
    35 int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
    36 int main()
    37 {
    38     scanf("%s",a);scanf("%s",b);
    39     n=strlen(a),m=strlen(b);
    40     for(N=1;N<=(n+m);N<<=1)++l;
    41     for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    42     for(int i=1;i<N;i<<=1)
    43         for(int k=0;k<i;++k)W[N/i*k]=(Complex){cos(k*Pi/i),sin(k*Pi/i)};
    44     for(int i=0;i<6;++i)
    45         for(int j=0;j<6;++j)
    46         {
    47             for(int k=0;k<N;++k)A[k].a=A[k].b=B[k].a=B[k].b=0;
    48             for(int k=0;k<n;++k)A[k].a=(a[k]==i+97);
    49             for(int k=0;k<m;++k)B[k].a=(b[m-k-1]==j+97);
    50             FFT(A,1);FFT(B,1);
    51             for(int k=0;k<N;++k)A[k]=A[k]*B[k];
    52             FFT(A,-1);
    53             for(int k=0;k<N;++k)eql[k][i][j]=(int)(A[k].a/N+0.5);
    54         }
    55     for(int i=m-1;i<n;++i)
    56     {
    57         for(int j=0;j<6;++j)f[j]=j;
    58 
    59         int ans=0;
    60 
    61         for(int j=0;j<6;++j)
    62             for(int k=0;k<6;++k)
    63                 if(eql[i][j][k])
    64                    {
    65                     if(getf(j) != getf(k))
    66                     {
    67                         ans ++ ;
    68                         f[getf(j)] = getf(k);
    69                     }
    70                    }
    71 
    72         printf("%d ",ans);
    73     }
    74     puts("");
    75     return 0;
    76 }




  • 相关阅读:
    Caffe + Ubuntu 15.04 + CUDA 7.0 新手安装配置指南
    姚斌分布式作业一
    一个简单正则表达式引擎的实现
    学习编程的方法
    [Leetcode]012. Integer to Roman
    [Leetcode]011. Container With Most Water
    JOS lab1 part2 分析
    我的Android Studio配置
    [Leetcode]009.Palindrome Number
    [Leetcode]008.String to Integer (atoi)
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11069165.html
Copyright © 2020-2023  润新知