题意
凯撒密码的映射规则是
给你一个加密表book[26](26个字母的排列)
原字符是a,加密后的字符是book[a-'a']
现在加密会出现问题,可能会相差1位,比如加密后是b,可能会显示a和c,解密是正常的
Alice将字符串T加密后E(T)发给Bob,Bob将这个字符串解密D(E(T))得到字符串S,问S和T在有误差的情况下是否相等
分析
考虑到加密和解密是一个相反操作
判断 D(E(T)) == T相当于 判断E(T) == E(S)
D操作是正确的,所以S的加密也是正确的
所以就是T串的值可能会有1的误差
这里类似于BZOJ4503
我们需要构造一个表达式,来表示S串中一位和T串中一位是不是有误差的相等
F(s,t) = (s-t)^2*((s-t)^2-1) = (s-t)^4 - (s-t)^2 这样当s == t 或者s == t-1 或者 s == t+1 时 F(s,t)==0,否则 F(s,t)>0
如果要整个连续的字符串都是相等的,那么就是∑F(s_i,t_j) == 0 ( j-i == k ) 为一个常数
将t串反向后,展开表达式满足卷积性质
所以求一个卷积就好了,其中为0的元素则是匹配位置
代码
#include<bits/stdc++.h>
using namespace std;
long long f[7][500005],g[7][500005],n_f,n_g;
char s1[250005],s2[250005],dic[30];
long long en[30],de[30],s[500005];
const double pi = acos(-1);
const double pi_2 = 2*pi;
struct Complex // 复数
{
double r,i;
Complex(double _r = 0, double _i = 0) :r(_r), i(_i) {}
Complex operator +(const Complex &b) {
return Complex(r + b.r, i + b.i);
}
Complex operator -(const Complex &b) {
return Complex(r - b.r, i - b.i);
}
Complex operator *(const Complex &b) {
return Complex(r*b.r - i*b.i, r*b.i + i*b.r);
}
}xf[1000005],xg[1000005];
void change(Complex y[],int len){
int i,j,k;
for(i=1,j=len/2;i<len-1;++i){
if(i<j)swap(y[i],y[j]);
k=len>>1;
for(;j>=k;j-=k,k>>=1);
if(j<k)j+=k;
}
}
void fft(Complex y[],int len,int on){
change(y,len);
for(int h=2;h<=len;h<<=1){
Complex wn(cos(-on*pi_2/h),sin(-on*pi_2/h));
for(int j=0;j<len;j+=h){
Complex w(1,0);
for(int k=j;k<j+h/2;++k){
Complex u=y[k],t=w*y[k+h/2];
y[k]=u+t;
y[k+h/2]=u-t;
w=w*wn;
}
}
}
if(on==-1)
for(int i=0;i<len;++i)
y[i].r/=len;
}
void debug()
{
long long k = n_f+ n_g-n_f-3 -1;
for(long long i = n_g-n_f,j=1;i>=0;i--,j++)
{
long long k = n_f+i-1;
cout<<j<<"::"<<(long long)(xf[k].r+0.5)<<endl;
}
cout<<s[k]<<endl;
cout<<endl;
}
int main()
{
scanf("%s%s%s",s1,s2,dic);
for(long long i =0 ;i<26;i++){
en[i] = dic[i]-'a';
de[dic[i]-'a'] = i;
}
n_f = strlen(s1);n_g = strlen(s2);
for(long long i = 0;i<n_f;i++) {
f[0][i] = 1LL;f[1][i] = en[s1[i]-'a'];
for(long long j = 2;j<=6;j++) f[j][i] = f[j-1][i]*f[1][i];
}
for(long long i = 0;i<n_g;i++)
{
g[0][n_g-i-1] = 1LL;g[1][n_g-i-1] = en[s2[i]-'a'];
for(long long j=2;j<=6;j++) g[j][n_g-i-1] = g[j-1][n_g-i-1] * g[1][n_g-i-1];
}
// for(long long i = 0;i<n_f;i++) cout<<f[1][i]<<" ";
// cout<<endl;
// for(long long i = 0;i<n_g;i++) cout<<g[1][i]<<" ";
// cout<<endl;
long long n = n_f+n_g+1;
long long len = 1;
while(len < n)len <<=1;
for(long long i = 0;i<n;i++) xf[i] = Complex(f[4][i],0),xg[i] = Complex(g[0][i],0);
for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
fft(xf,len,1);fft(xg,len,1);
for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
fft(xf,len,-1);
for(long long i=0;i<=n_g-n_f;i++){
long long k = n_f+i-1;
s[k]+=(long long)(xf[k].r+0.5);
}
for(long long i = 0;i<n;i++) xf[i] = Complex(f[0][i],0),xg[i] = Complex(g[4][i],0);
for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
fft(xf,len,1);fft(xg,len,1);
for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
fft(xf,len,-1);
for(long long i=0;i<=n_g-n_f;i++){
long long k = n_f+i-1;
s[k]+=(long long)(xf[k].r+0.5);
}
for(long long i = 0;i<n;i++) xf[i] = Complex(f[3][i],0),xg[i] = Complex(g[1][i],0);
for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
fft(xf,len,1);fft(xg,len,1);
for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
fft(xf,len,-1);
for(long long i=0;i<=n_g-n_f;i++){
long long k = n_f+i-1;
s[k]-=4*(long long)(xf[k].r+0.5);
}
for(long long i = 0;i<n;i++) xf[i] = Complex(f[1][i],0),xg[i] = Complex(g[3][i],0);
for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
fft(xf,len,1);fft(xg,len,1);
for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
fft(xf,len,-1);
for(long long i=0;i<=n_g-n_f;i++){
long long k = n_f+i-1;
s[k]-=4*(long long)(xf[k].r+0.5);
}
for(long long i = 0;i<n;i++) xf[i] = Complex(f[2][i],0),xg[i] = Complex(g[2][i],0);
for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
fft(xf,len,1);fft(xg,len,1);
for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
fft(xf,len,-1);
for(long long i=0;i<=n_g-n_f;i++){
long long k = n_f+i-1;
s[k]+=6*(long long)(xf[k].r+0.5);
}
for(long long i = 0;i<n;i++) xf[i] = Complex(f[2][i],0),xg[i] = Complex(g[0][i],0);
for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
fft(xf,len,1);fft(xg,len,1);
for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
fft(xf,len,-1);
for(long long i=0;i<=n_g-n_f;i++){
long long k = n_f+i-1;
s[k]-=(long long)(xf[k].r+0.5);
}
for(long long i = 0;i<n;i++) xf[i] = Complex(f[0][i],0),xg[i] = Complex(g[2][i],0);
for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
fft(xf,len,1);fft(xg,len,1);
for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
fft(xf,len,-1);
for(long long i=0;i<=n_g-n_f;i++){
long long k = n_f+i-1;
s[k]-=(long long)(xf[k].r+0.5);
}
for(long long i = 0;i<n;i++) xf[i] = Complex(f[1][i],0),xg[i] = Complex(g[1][i],0);
for(long long i = n;i<len;i++) xf[i] = xg[i] = Complex(0,0);
fft(xf,len,1);fft(xg,len,1);
for(long long i = 0;i<len;i++) xf[i] = xf[i] * xg[i];
fft(xf,len,-1);
for(long long i=0;i<=n_g-n_f;i++){
long long k = n_f+i-1;
s[k]+=2*(long long)(xf[k].r+0.5);
}
vector<long long>ans;
for(long long i = n_g-n_f,j=1;i>=0;i--,j++)
{
long long k = n_f+i-1;
// cout<<j<<"::"<<s[k]<<endl;
if(s[k] == 0) ans.push_back(j);
}
// cout<<endl;
int nn = ans.size();
printf("%d",nn);
if(nn)
{
puts("");
for(long long i =0 ;i<nn;i++)
{
printf("%lld ",ans[i]);
}
}
}