题目传送门
分析:
我们先看看如果不需要置换,我们如何将(S)匹配进(T)
(废话当然是kmp或者hash了
能否用函数求解呢?
两个字符(S_i,T_j)相同,当且仅当((S_i-T_j)^2=0)
于是对于串(T),以结束位置为自变量做一个函数(P(x)),把(S)串反转
(P(x)=sum_{i=1}^{m}(S_i-T_{x+i-m})^2)
当(P(x)=0)时,说明这个位置结束的串可以匹配
式子展开,中间的(S_{i}T_{j})用NTT求一下就好了
接下来考虑置换,同理
两个字符(S_i,T_j)相同,当且仅当((S_i-T_j)^2(P_{S_i}-T_j)^2=0)
同样适用NTT求解(但是要做7次)
我反正没卡过时限,考虑奇奇怪怪的技巧
我们尝试把平方抹去,(P(x))变成
(P(x)=sum_{i=1}^{m}(S_i-T_{x+i-m})(P_{S_i}-T_{x+i-m}))
这个明显是错误的,在(S)和(T)值域只有([1,26])时随随便便就挂了
那就把值域变一下,把每个字符的值在NTT模数取模下随机
这样正确率就很高了
(还可能被卡?换个NTT模数,998244353众人皆知,1004535809就很棒
我用的998244353,到时候视情况而定吧(也可以随机两次或者三次来做
反正就是乱搞(
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
#define maxn 800005
#define INF 0x3f3f3f3f
#define MOD 998244353
using namespace std;
inline long long getint()
{
long long num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
}
int n,m;
int A[maxn],B[maxn],F[maxn],G[maxn],H[maxn],p[maxn],P[maxn];
int pre[maxn],rev[maxn],w[maxn];
char S[maxn],T[maxn];
int ans,sum;
inline int upd(int x){return x<MOD?x:x-MOD;}
inline int ksm(int num,int k)
{
int ret=1;
for(;k;k>>=1,num=1ll*num*num%MOD)if(k&1)ret=1ll*ret*num%MOD;
return ret;
}
inline void NTT(int *a,int len,int op)
{
for(int i=0;i<len;i++)if(i<rev[i])swap(a[i],a[rev[i]]);
for(int i=1;i<len;i<<=1)for(int j=0,wn=ksm(op==1?3:332748118,(MOD-1)/(i<<1));j<len;j+=(i<<1))
for(int k=0,w=1;k<i;k++,w=1ll*w*wn%MOD)
{
int x=a[j+k],y=1ll*a[i+j+k]*w%MOD;
a[j+k]=upd(x+y),a[i+j+k]=upd(x-y+MOD);
}
if(!~op)for(int i=0,Inv=ksm(len,MOD-2);i<len;i++)a[i]=1ll*a[i]*Inv%MOD;
}
inline void mul(int *a,int *b)
{
int len=1;
while(len<(n+m))len<<=1;
for(int i=0;i<len;i++)rev[i]=(rev[i>>1]>>1)|(i&1?len>>1:0);
NTT(a,len,1),NTT(b,len,1);
for(int i=0;i<len;i++)a[i]=1ll*a[i]*b[i]%MOD;
NTT(a,len,-1);
}
int main()
{
for(int i=1;i<=26;i++)p[i]=getint();
scanf("%s%s",S,T);
n=strlen(T),m=strlen(S);
for(int i=0;i<m-i-1;i++)swap(S[i],S[m-i-1]);
for(int i=1;i<=26;i++)w[i]=ksm(p[i],INF);
for(int i=0;i<n;i++)
{
F[i]=w[T[i]-96];
pre[i]=upd((i?pre[i-1]:0)+1ll*F[i]*F[i]%MOD);
}
for(int i=0;i<m;i++)
{
G[i]=w[S[i]-96];
H[i]=w[p[S[i]-96]];
sum=upd(sum+1ll*G[i]*H[i]%MOD);
}
for(int i=0;i<n;i++)A[i]=F[i];
for(int i=0;i<m;i++)B[i]=upd(G[i]+H[i]);
mul(A,B);
for(int i=0;i<n+m;i++)P[i]=upd(MOD-A[i]);
for(int i=m-1;i<n;i++)
{
P[i]=upd(P[i]+upd(pre[i]-(i>=m?pre[i-m]:0)+MOD));
P[i]=upd(P[i]+sum);
printf("%d",!P[i]);
}
printf("
");
}