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 }




猜你喜欢

转载自www.cnblogs.com/zhangbuang/p/11069165.html