好题啊
kmp+树状数组
可以加深 kmp的理解
在求next数组的时候 匹配条件不应该是 b[i]=b[j]吗 我们把他改成 我们体力所需要的条件 也就是rank[i]=rank[j] rank是什么呢就是当前数前面比他小的和和他相等的,只要跟模式串一样就ok
所以 就ok了
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 1000005
#define maxm 25005
using namespace std;
//by mars_ch
int next[maxm],pos[maxn];
int s[maxn],eq[maxn];
int a[maxn],b[maxm];
int c[maxm];
int n,k,S,all;
int lowbit(int x)
{
return x&(-x);
}
void updata(int x,int y)
{
while(x<=S)
{
c[x]+=y;
x+=lowbit(x);
}
}
int sum(int x)
{
int res=0;
while(x)
{
res+=c[x];
x-=lowbit(x);
}
return res;
}
void getnext()
{
int i=1,j=0,kk;
next[1]=0;
while(i<=k)
{
if(j==0 || (sum(b[i]-1)==s[j] && sum(b[i]) == eq[j]))
{
i++,j++;
next[i]=j;
if(i==k+1) return ;
updata(b[i],1);
}
else
{
for(kk=i-j+1;kk<=i-next[j];kk++) //这里对next[j]之前的b[i]都要消除
updata(b[kk],-1);
j=next[j];
}
}
}
int kmp()
{
int i=1,j=1,f;
updata(a[1],1);
while(i<=n)
{
if(j==0 ||(sum(a[i]-1)==s[j] && sum(a[i])==eq[j]))
{
++i,++j;
if(i<=n)
updata(a[i],1);
}
else
{
for(f=i-j+1;f<=i-next[j];f++)
updata(a[f],-1);
j=next[j];
}
if(j>k)
{
for(f=i-j+1;f<=i-next[j];f++)
updata(a[f],-1);
all++;
pos[all]=i-1;
j=next[j];
}
}
return all;
}
int main()
{
scanf("%d%d%d",&n,&k,&S);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=k;i++)
{
scanf("%d",&b[i]);
updata(b[i],1);
s[i]=sum(b[i]-1);
eq[i]=sum(b[i]);
}
memset(c,0,sizeof(c));
getnext();
memset(c,0,sizeof(c));
printf("%d\n",kmp());
for(int i=1;i<=all;i++)
{
printf("%d\n",pos[i]-k+1);
}
}