T1
题解
我们并不需要知道相对应位置的数字是不是相等,只要置换之后的hash值相等就行了。
hash 函数本身相当于每个位置乘上 x 的若干次方,置换之后只要改变次方的顺序就好了。
具体来说,设我们的base值是m,一段区间的hash值是 ,然后一个置换的hash值是
如果我们设 ,那么我们要求的置换的hash值是 ,这是一个非常明显的卷积
那么同理一段区间的hash值也可以通过倒置的方法用卷积求出来,最后只要判断两者是不是相等就行了
代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
const int N=1500005;
const int mod=998244353;
const int base=131;
int n,m,c,fn,r[N];LL mi[N],hash1[N],hash2[N],s[N],p[N];
LL ksm(LL a,LL k)
{
LL ans=1;
for (;k;k>>=1,a=a*a%mod)
if (k&1) ans=ans*a%mod;
return ans;
}
void NTT(LL *a,int id)
{
for (int i=0;i<n;i++)
if (i<r[i]) swap(a[i],a[r[i]]);
for (int k=1;k<n;k<<=1)
{
LL wn=ksm(3,(mod-1)/(k<<1));
for (int i=0;i<n;i+=(k<<1))
{
LL w=1;
for (int j=0;j<k;j++,w=w*wn%mod)
{
LL x=a[i+j],y=w*a[i+j+k]%mod;
a[i+j]=(x+y)%mod; a[i+j+k]=(x-y+mod)%mod;
}
}
}
if (id==-1) reverse(a+1,a+n);
}
int main()
{
freopen("sub.in","r",stdin);
freopen("sub.out","w",stdout);
scanf("%d%d%d",&n,&m,&c);
for (int i=0;i<n;i++) scanf("%lld",&p[i]),p[i]--;
for (int i=0;i<m;i++) scanf("%lld",&s[i]);
mi[0]=1;
for (int i=1;i<n;i++) mi[i]=mi[i-1]*base%mod;
for (int i=0;i<n;i++) hash1[i]=mi[n-i-1];
for (int i=0;i<n;i++) hash2[n-i-1]=mi[p[i]];
int fn=n;int L=0;
for (n=1;n<=m*2;n<<=1) L++;
for (int i=0;i<n;i++) r[i]=(r[i>>1]>>1) | ((i&1)<<L-1);
NTT(s,1); NTT(hash1,1); NTT(hash2,1);
for (int i=0;i<n;i++) hash1[i]=hash1[i]*s[i]%mod,hash2[i]=hash2[i]*s[i]%mod;
NTT(hash1,-1); NTT(hash2,-1);
for (int i=0;i<=m-fn;i++)
if (hash1[i+fn-1]==hash2[i+fn-1]) printf("1");else printf("0");
}