题意即为在序列中找出给定排列能匹配相同的位置,这里的匹配相同指的是相对大小关系相同,即离散化后相同。
因为是相对大小关系相同,所以只需考虑每个数所在的排名。可以对给定排列处理出 (num_i),为位置 (i) 之前小于位置 (i) 对应的数的个数,发现对于序列,(num_i) 相同,相对大小关系就相同。
那么就只用考虑序列和给定排列 (num_i) 的匹配,这个可以通过 (KMP) 来实现,用树状数组来维护,匹配成功时在树状数组上加入贡献,失配时在树状数组上删去贡献。
(code:)
#include<bits/stdc++.h>
#define maxn 1000010
#define lowbit(x) (x&(-x))
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,m,pos,cnt;
int p[maxn],a[maxn],s[maxn],t[maxn],num[maxn],nxt[maxn],ans[maxn];
void update(int x,int v)
{
while(x<=m) t[x]+=v,x+=lowbit(x);
}
int query(int x)
{
int v=0;
while(x) v+=t[x],x-=lowbit(x);
return v;
}
void clear()
{
pos=0;
for(int i=1;i<=m;++i) t[i]=0;
}
int main()
{
read(n),read(m),num[n+1]=-1;
for(int i=1;i<=n;++i)
{
int x;
read(x),p[x]=i;
}
for(int i=1;i<=m;++i) read(a[i]),s[i]=a[i];
sort(s+1,s+m+1);
for(int i=1;i<=m;++i) a[i]=lower_bound(s+1,s+m+1,a[i])-s;
for(int i=1;i<=n;++i) num[i]=query(p[i]),update(p[i],1);
clear();
for(int i=2;i<=n;++i)
{
while(pos&&query(p[i])!=num[pos+1])
{
for(int j=i-pos;j<i-nxt[pos];++j) update(p[j],-1);
pos=nxt[pos];
}
if(query(p[i])==num[pos+1]) update(p[i],1),pos++;
nxt[i]=pos;
}
clear();
for(int i=1;i<=m;++i)
{
while(pos&&query(a[i])!=num[pos+1])
{
for(int j=i-pos;j<i-nxt[pos];++j) update(a[j],-1);
pos=nxt[pos];
}
if(query(a[i])==num[pos+1]) update(a[i],1),pos++;
if(pos==n) ans[++cnt]=i-n+1;
}
printf("%d
",cnt);
for(int i=1;i<=cnt;++i) printf("%d ",ans[i]);
return 0;
}