两个串匹配的话意思就是每一位对应的排序序号相等。即比它大比它小的数目对应相同。
那么就可以用kmp来做了,匹配的时候相等的条件改成判断两个位置的数字排序位是否相等。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn=1e5+9; int a[maxn],b[maxn],cnt[maxn/4][30],next[maxn]; int cnt1[maxn][30],suma[maxn][30],sumb[maxn][30]; bool flag[maxn]; int n,m,s; void getnext() { memset(cnt,0,sizeof(cnt)); memset(sumb,0,sizeof(sumb)); for(int i=1;i<=m;i++) cnt[i][b[i]+1]++; for(int i=1;i<=m;i++) for(int j=1;j<=25;j++) cnt[i][j]+=cnt[i][j-1]; for(int i=1;i<=m;i++) for(int j=1;j<=25;j++) cnt[i][j]+=cnt[i-1][j]; for(int i=1;i<=m;i++) sumb[i][b[i]]++; for(int i=1;i<=m;i++) for(int j=1;j<=25;j++) sumb[i][j]+=sumb[i-1][j]; memset(next,0,sizeof(next)); next[1]=0; for(int i=2;i<=m;i++) { int tmp=next[i-1]; while(tmp) { if(cnt[i][b[i]]-cnt[i-tmp-1][b[i]]==cnt[tmp+1][b[tmp+1]]&&(sumb[i][b[i]]-sumb[i-tmp-1][b[i]]==sumb[tmp+1][b[tmp+1]])) { next[i]=tmp+1; break; } tmp=next[tmp]; } if(cnt[i][b[i]]-cnt[i-tmp-1][b[i]]==cnt[tmp+1][b[tmp+1]]) if(sumb[i][b[i]]-sumb[i-tmp-1][b[i]]==sumb[tmp+1][b[tmp+1]]) next[i]=tmp+1; } } int main() { // freopen("in.txt","r",stdin); while(scanf("%d %d %d",&n,&m,&s)!=EOF) { for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) scanf("%d",&b[i]); getnext(); memset(flag,0,sizeof(flag)); memset(cnt1,0,sizeof(cnt1)); memset(suma,0,sizeof(suma)); for(int i=1;i<=n;i++) cnt1[i][a[i]+1]++; for(int i=1;i<=n;i++) for(int j=1;j<=25;j++) cnt1[i][j]+=cnt1[i][j-1]; for(int i=1;i<=n;i++) for(int j=1;j<=25;j++) cnt1[i][j]+=cnt1[i-1][j]; for(int i=1;i<=n;i++) suma[i][a[i]]++; for(int i=1;i<=n;i++) for(int j=1;j<=25;j++) suma[i][j]+=suma[i-1][j]; for(int i=1,j=1;i<=n;i++) { while(j>1) { if(cnt[j][b[j]]!=cnt1[i][a[i]]-cnt1[i-j][a[i]]) j=next[j-1]+1; else if(sumb[j][b[j]]!=suma[i][a[i]]-suma[i-j][a[i]]) j=next[j-1]+1; else break; } if(cnt[j][b[j]]==cnt1[i][a[i]]-cnt1[i-j][a[i]]&&(sumb[j][b[j]]==suma[i][a[i]]-suma[i-j][a[i]])) { if(j==m) { flag[i-j+1]=1; j=next[j]+1; } else j++; } } int ans=0; for(int i=1;i<=n;i++) ans+=flag[i]; cout<<ans<<endl; for(int i=1;i<=n;i++) if(flag[i]) printf("%d\n",i); } return 0; }