题意:定义两个相同长度为
n
n
n的字符串
s
,
t
s,t
s,t,
m
i
s
(
s
,
t
)
=
∑
i
=
1
i
=
n
(
s
[
i
[
!
=
t
[
i
]
)
mis(s,t)=\sum\limits_{i=1}^{i=n}(s[i[!=t[i])
mis(s,t)=i=1∑i=n(s[i[!=t[i])
定义字符串
s
s
s,若
s
s
s满足
m
i
s
(
s
[
1
]
.
.
.
s
[
n
−
d
]
,
s
[
d
+
1
]
.
.
.
s
[
n
]
)
≤
d
mis(s[1]...s[n-d],s[d+1]...s[n])\le d
mis(s[1]...s[n−d],s[d+1]...s[n])≤d
则该字符串为 nearly d-periodic,给你一个长度为
n
n
n的字符串
s
s
s和长度为
m
m
m的字符串
t
t
t,保证两个字符串都是 nearly d-periodic,求对任意
i
∈
[
1
,
n
−
m
+
1
]
i∈[1,n-m+1]
i∈[1,n−m+1],
m
i
s
(
s
[
i
]
.
.
.
s
[
i
+
m
−
1
]
,
t
[
1
]
.
.
t
[
m
]
)
mis(s[i]...s[i+m-1],t[1]..t[m])
mis(s[i]...s[i+m−1],t[1]..t[m]).
题解:
对于
i
i
i,我们可以把求不同转成总数减去相同的。
现在求相同:以下下标均从0开始。
∗
*
∗为卷积,
⋅
\cdot
⋅为乘
分别对不同字符求贡献。
下面仅对一种字符
s
t
st
st展开讨论(其他都是一样的)
令
f
[
j
]
=
(
s
[
j
]
=
=
s
t
)
f[j]=(s[j]==st)
f[j]=(s[j]==st);
令
g
[
j
]
=
(
t
[
j
]
=
=
s
t
)
g[j]=(t[j]==st)
g[j]=(t[j]==st);
那么对于
i
i
i,
s
t
st
st产生的贡献便是
∑
k
=
0
k
=
m
−
1
f
[
i
+
k
]
⋅
g
[
k
]
\sum\limits_{k=0}^{k=m-1}f[i+k]\cdot g[k]
k=0∑k=m−1f[i+k]⋅g[k];
因为对于同个位置,只有
s
s
s和
t
t
t都是
s
t
st
st才能产生贡献。
这样好像看不出什么东西。
但如果把
t
t
t字符串翻转一下,那么
g
g
g数组同样也会翻转,即
g
[
j
]
=
g
[
m
−
1
−
j
]
g[j]=g[m-1-j]
g[j]=g[m−1−j]
那么贡献就变成
∑
k
=
0
k
=
m
−
1
f
[
i
+
k
]
⋅
g
[
m
−
1
−
k
]
\sum\limits_{k=0}^{k=m-1}f[i+k]\cdot g[m-1-k]
k=0∑k=m−1f[i+k]⋅g[m−1−k]
看着像啥?多项式相乘啊!
i
+
k
+
m
−
1
−
k
=
m
−
1
+
i
i+k+m-1-k=m-1+i
i+k+m−1−k=m−1+i相对于特定的
i
i
i是一个定值
也就是说你做一下卷积后,
(
f
∗
g
)
(
m
−
1
+
i
)
(f*g)(m-1+i)
(f∗g)(m−1+i)就是
s
t
st
st的贡献了
大概你会马上想到什么
F
F
T
,
N
T
T
FFT,NTT
FFT,NTT啥的搞一下,但是这些都是
n
l
o
g
n
nlogn
nlogn的复杂度,而字符范围有26,
n
是
1
e
6
n是1e6
n是1e6,复杂度会变成
O
(
26
n
l
o
g
n
)
O(26 nlog n)
O(26nlogn)是肯定不能接受的
但是还有一个条件没有用,
s
,
t
s,t
s,t都是 nearly d-periodic ,
也就是说(
∑
i
=
−
∞
+
∞
(
f
[
i
]
−
f
[
i
+
d
]
)
)
≤
d
\sum\limits_{i=-\infty}^{+\infty}(f[i]-f[i+d]))\le d
i=−∞∑+∞(f[i]−f[i+d]))≤d
那么我们便可以定义:
D
f
[
i
]
=
f
[
i
]
−
f
[
i
+
d
]
Df[i]=f[i]-f[i+d]
Df[i]=f[i]−f[i+d]
D
g
[
i
]
=
g
[
i
]
−
g
[
i
+
d
]
Dg[i]=g[i]-g[i+d]
Dg[i]=g[i]−g[i+d]
而且保证了
D
f
[
i
]
和
D
g
[
i
]
的
非
零
系
数
只
有
O
(
d
)
项
Df[i]和Dg[i]的非零系数只有O(d)项
Df[i]和Dg[i]的非零系数只有O(d)项,而
d
d
d很小
将下标扩展到整数范围。
则
(
D
f
∗
D
g
)
i
=
∑
u
+
v
=
i
D
f
[
u
]
⋅
D
g
[
v
]
(Df*Dg)i=\sum\limits_{u+v=i}Df[u]\cdot Dg[v]
(Df∗Dg)i=u+v=i∑Df[u]⋅Dg[v]
接下来推公式
(
D
f
∗
D
g
)
i
(Df*Dg)i
(Df∗Dg)i
=
∑
u
+
v
=
i
(
f
[
u
]
−
f
[
u
+
d
]
)
(
g
[
v
]
−
g
[
v
+
d
]
)
=\sum\limits_{u+v=i}(f[u]-f[u+d])(g[v]-g[v+d])
=u+v=i∑(f[u]−f[u+d])(g[v]−g[v+d])
=
∑
u
+
v
=
i
(
f
[
u
]
⋅
g
[
v
]
−
f
[
u
+
d
]
⋅
g
[
v
]
−
f
[
u
]
⋅
g
[
v
+
d
]
+
f
[
u
+
d
]
⋅
g
[
v
+
d
]
=\sum\limits_{u+v=i}(f[u]\cdot g[v]-f[u+d]\cdot g[v]-f[u]\cdot g[v+d]+f[u+d]\cdot g[v+d]
=u+v=i∑(f[u]⋅g[v]−f[u+d]⋅g[v]−f[u]⋅g[v+d]+f[u+d]⋅g[v+d]
=
∑
u
+
v
=
i
f
[
u
]
⋅
g
[
v
]
−
∑
x
+
y
=
i
+
d
2
⋅
f
[
x
]
⋅
g
[
y
]
+
∑
x
+
y
=
i
+
2
d
f
[
x
]
⋅
g
[
y
]
=\sum\limits_{u+v=i}f[u]\cdot g[v]-\sum\limits_{x+y=i+d}2\cdot f[x]\cdot g[y]+\sum\limits_{x+y=i+2d}f[x]\cdot g[y]
=u+v=i∑f[u]⋅g[v]−x+y=i+d∑2⋅f[x]⋅g[y]+x+y=i+2d∑f[x]⋅g[y]
=
(
f
∗
g
)
i
−
2
⋅
(
g
∗
f
)
(
i
+
d
)
+
(
g
∗
f
)
(
i
+
2
d
)
=(f*g)i-2\cdot(g*f)(i+d)+(g*f)(i+2d)
=(f∗g)i−2⋅(g∗f)(i+d)+(g∗f)(i+2d)
也就是说
(
f
∗
g
)
i
=
(
D
f
∗
D
g
)
i
+
2
(
f
∗
g
)
(
i
+
d
)
−
(
f
∗
g
)
(
i
+
2
d
)
(f*g)i=(Df*Dg)i+2(f*g)(i+d)-(f*g)(i+2d)
(f∗g)i=(Df∗Dg)i+2(f∗g)(i+d)−(f∗g)(i+2d)
那么对于字符
s
t
st
st的贡献便是
(
f
∗
g
)
(
m
−
1
+
i
)
(f*g)(m-1+i)
(f∗g)(m−1+i)
对26个字符求一下和就是最终相同位置的数量
s
a
m
e
same
same,然后
m
−
s
a
m
e
m-same
m−same就是答案了
如果你觉得还不错,点个赞再走呗,如果还有疑问(纠正),请指出。
代码(基本跟标程没啥区别,毕竟看着它理解的):
#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define fi first
#define se second
#define mp make_pair
#define endl '\n'
const int MX=2e6+7;
using namespace std;
vector<pair<int,int>>v1[30],v2[30];//v1[i]存在字符i的f值,如f[v[i][0].first]=v[i][0].secon,v2存g的;
char s[MX],t[MX];
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
int d;
cin>>d;
cin>>s>>t;
int n=strlen(s),m=strlen(t);
reverse(t,t+m);//令g[m-1-j]=g[j];
//对于f[i]-f[i+d]=0部分,和g[i]-g[i+d]=0部分是无用的,对答案没有贡献,所以整个整数范围可能产生非零的只有[-d,n-1](对于f)和[-d,m-1](对于g) )
for(int i=0;i<d;i++)v1[s[i]-'a'].pb(mp(i-d,-1)),v2[t[i]-'a'].pb(mp(i-d,-1));//存Df[-d...-1]和Dg[-d...-1]
for(int i=0;i<n;i++)//存Df[0..n-1]
{
if(s[i]!=s[i+d])
{
v1[s[i]-'a'].pb(mp(i,1));//说明,f[i]=1,f[i+d]=0,所以Df[i]=1;
if(i+d<n)v1[s[i+d]-'a'].pb(mp(i,-1));//说明f[i]=0,f[i+d]=1,Df[i]=-1
}
}
for(int i=0;i<m;i++)//Dg[0...m-1]
{
if(t[i]!=t[i+d])
{
v2[t[i]-'a'].pb(mp(i,1));
if(i+d<m)v2[t[i+d]-'a'].pb(mp(i,-1));
}
}
vector<int>cnt(n+m,0);
//求Df*Dg
for(int i=0;i<26;i++)
for(auto f:v1[i])
for(auto g:v2[i])
if(f.fi+g.fi>=m-1) cnt[f.fi+g.fi]+=f.se*g.se;
//
vector<int>same(n+m+2*d,0);
//从Df*Dg得到f*g
for(int i=n+m-2;i>=m-1;i--)same[i]=cnt[i]+2*same[i+d]-same[i+2*d];
for(int i=0;i<=n-m;i++)cout<<m-same[m-1+i]<<endl;
}