分析:
又是一道经典的FFT做字符串匹配的问题。
题目要求做一定次数的操作,使得最终所有相匹配的字符一样。
可以将这个字符映射到一个图上,如果这种匹配情况下有一个字符 匹配的是 ,那么就在图中 点向 点连一条边。最终图中的每个联通块的大小-1就是操作次数。(其实可以用并查集实现,操作次数就是并查集中的合并次数)
所以枚举每一种匹配关系,比如如果考虑 字符与 字符匹配的情况,则令原串中所有x为1,模式串中所有y为1,将模式串翻转,再卷积。然后再令原串中所有y为1,模式串中所有x为1,再翻转做一次。两种情况得到的结果的和,就表示这种情况的数量,对每一位不为0的,就连上 到 这条边。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#define SF scanf
#define PF printf
#define MAXN 300000
using namespace std;
typedef long long ll;
int siz;
const double Pi=acos(-1);
struct cpx{
double r,i;
cpx() {}
cpx(double _r,double _i):r(_r),i(_i) {}
cpx operator * (const cpx &a) const{
return cpx(r*a.r-i*a.i,r*a.i+i*a.r);
}
cpx operator + (const cpx &a) const{
return cpx(r+a.r,i+a.i);
}
cpx operator - (const cpx &a) const{
return cpx(r-a.r,i-a.i);
}
};
void fft(cpx *a,int f,int N){
int i,j,k;
for(i=1,j=0;i<N;i++){
for(int d=N;j^=d>>=1,~j&d;);
if(i<j)
swap(a[i],a[j]);
}
for(i=1;i<N;i<<=1){
cpx wn(cos(Pi/i),f*sin(Pi/i));
for(j=0;j<N;j+=i<<1){
cpx w(1,0);
for(k=0;k<i;k++,w=w*wn){
cpx x=a[j+k],y=w*a[i+j+k];
a[j+k]=x+y;
a[i+j+k]=x-y;
}
}
}
if(f==-1)
for(i=0;i<N;i++)
a[i].r/=N;
}
cpx A[MAXN],B[MAXN];
int n;
int sum[MAXN],res[MAXN],fa[10][MAXN],len1,len2;
char s1[MAXN],s2[MAXN];
void solve(char x,char y){
memset(A,0,sizeof A);
memset(B,0,sizeof B);
for(int i=0;i<len1;i++)
if(s1[i]==x)
A[i].r=1;
for(int i=0;i<len2;i++)
if(s2[i]==y)
B[len2-i-1].r=1;
fft(A,1,siz);
fft(B,1,siz);
for(int i=0;i<siz;i++)
A[i]=A[i]*B[i];
fft(A,-1,siz);
for(int i=0;i<siz;i++)
res[i]+=int(A[i].r+0.5);
}
int get_fa(int id,int x){
if(fa[x][id]==0)
return x;
fa[x][id]=get_fa(id,fa[x][id]);
return fa[x][id];
}
void link(int x,int y,int id){
int u=get_fa(id,x);
int v=get_fa(id,y);
if(u!=v){
fa[u][id]=v;
sum[id]++;
}
}
int main(){
SF("%s%s",s1,s2);
len1=strlen(s1);
len2=strlen(s2);
siz=1;
while(siz<=len1+len2)
siz<<=1;
for(int i='a';i<='f';i++)
for(int j='a';j<='f';j++){
if(i==j)
continue;
memset(res,0,sizeof res);
solve(i,j);
solve(j,i);
for(int k=0;k<len1;k++)
if(res[k]>0)
link(i-'a',j-'a',k);
}
for(int i=len2-1;i<len1;i++)
PF("%d ",sum[i]);
}