Educational Codeforces Round 40 I. Yet Another String Matching Problem

时间:2023-03-09 06:28:25
Educational Codeforces Round 40 I. Yet Another String Matching Problem

http://codeforces.com/contest/954/problem/I

给你两个串s,p,求上一个串的长度为|p|的所有子串和p的差距是多少,两个串的差距就是每次把一个字符变成另一个字符的最小次数,字符最大到f

很明显,如果知道每两个串对应地方不相同的字符就能通过dfs/dsu解出来,那么如何快速的找到所有对应的不匹配的地方呢,

我们先单独考虑两个不同的字符,比如abada中取a,cba中取c,用二进制1代表选取的字符表示就是10101,100,我们用fft来加速这一过程

1  2  3  4  5    1  2  3     ------->     n-1 n-2 n-3

1  0  1  0  1    1  0  0       1  0   0

4  3  1

0  0  1

直接乘的话复杂度还是很高,我们把后一个串转一下变成001,这样如果要找最开始的串和p匹配是不是就系数是5看fft之后的系数是不是1,然后以此类推第二个是6,这样一遍fft就能求出所有情况,然后一共需要fft6*6次,复杂度(O(36*nlogn))

#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod (1000000007)
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pii pair<int,int>
//#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-;
const int N=+,maxn=+,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; struct cd
{
double x,y;
cd(double _x=0.0,double _y=0.0):x(_x),y(_y){}
cd operator + (const cd &b)const
{
return cd(x+b.x,y+b.y);
}
cd operator - (const cd &b)const
{
return cd(x-b.x,y-b.y);
}
cd operator * (const cd &b)const
{
return cd(x*b.x-y*b.y,x*b.y+y*b.x);
}
cd operator / (const double &b)const
{
return cd(x/b,y/b);
}
}a[N<<],b[N<<];
int rev[N<<];
void getrev(int bit)
{
for(int i=; i<(<<bit); i++)
rev[i]=(rev[i>>]>>)|((i&)<<(bit-));
}
void fft(cd* a,int n,int dft)
{
for(int i=; i<n; i++)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int step=; step<n; step<<=)
{
cd wn(cos(dft*pi/step),sin(dft*pi/step));
for(int j=; j<n; j+=step<<)
{
cd wnk(,);
for(int k=j; k<j+step; k++)
{
cd x=a[k];
cd y=wnk*a[k+step];
a[k]=x+y;
a[k+step]=x-y;
wnk=wnk*wn;
}
}
}
if(dft==-)for(int i=; i<n; i++)a[i]=a[i]/n;
}
char s[N],p[N];
bool ok[N][][];
int fa[];
int Find(int x)
{
return fa[x]==x?x:fa[x]=Find(fa[x]);
}
int main()
{
scanf("%s%s",s+,p+);
int n=strlen(s+),m=strlen(p+);
int sz=;
while((<<sz)<n)sz++;
sz++;getrev(sz);
for(int i=;i<;i++)
{
for(int j=;j<;j++)
{
if(i==j)continue;
for(int k=;k<=(<<sz);k++)a[k]=b[k]=;
for(int k=;k<=n;k++)a[k]=(s[k]==i+'a');
for(int k=;k<=m;k++)b[n-k]=(p[k]==j+'a');
fft(a,(<<sz),);fft(b,(<<sz),);
for(int k=;k<=(<<sz);k++)a[k]=a[k]*b[k];
fft(a,(<<sz),-);
for(int k=;k<=n-m;k++)ok[k][i][j]=(a[n+k].x>=0.5);
}
}
for(int i=;i<=n-m;i++)
{
for(int j=;j<;j++)fa[j]=j;
int ans=;
for(int j=;j<;j++)
{
for(int k=;k<;k++)
{
if(j==k)continue;
int fj=Find(j),fk=Find(k);
if(ok[i][j][k]&&fj!=fk)fa[fj]=fk,ans++;
}
}
printf("%d ",ans);
}
puts("");
return ;
}
/********** **********/