很显然想到一种思路,把kmp的匹配模式改为当前位字符和上次出现位置的相对距离进行匹配
然后做法就很显然
同时处理一种特殊情况,如果位置差大于匹配长度时,直接视为没有出现过
c o d e code code
#include<iostream>
#include<cstring>
#include<cstdio>
#define solve(x, y) (x<y?x:0)
using namespace std;
int t, t1;
int n, m, sum, ans[1001000];
int a[1001000], b[1001000], last[1001000];
int nxt[1001000];
void next_()
{
nxt[1]=0;
int k=0;
for(int i=1; i<m; i++)
{
while(k&&solve(b[i+1], k+1)!=solve(b[k+1], k+1))
k=nxt[k];
if(solve(b[i+1], k+1)==solve(b[k+1], k+1))
k++;
nxt[i+1]=k;
}
}
void kmp()
{
int k=0;
for(int i=1; i<=n; i++)
{
while(k&&solve(a[i], k+1)!=solve(b[k+1], k+1))
k=nxt[k];
if(solve(a[i], k+1)==solve(b[k+1], k+1))
k++;
if(k==m)
{
ans[++sum]=i-m+1;
k=nxt[k];
}
}
}
int main()
{
scanf("%d%d", &t, &t1);
while(t--)
{
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++)
{
int x;
scanf("%d", &x);
a[i]=i-last[x];
last[x]=i;
}
memset(last, 0, sizeof(last));
for(int i=1; i<=m; i++)
{
int x;
scanf("%d", &x);
b[i]=i-last[x];
last[x]=i;
}
next_();
kmp();
printf("%d\n", sum);
for(int i=1; i<=sum; i++)
printf("%d ", ans[i]);
printf("\n");
sum=0, memset(last, 0, sizeof(last));
}
return 0;
}