LOJios
發現要作的是排名串的匹配。
而後咱們考慮把它轉成這個位置以前有多少個數小於當前這個數,這樣子只要每一個位置都對應相等那麼必定是合法的。
而後就能夠相似\(KMP\)的預處理出一個\(nxt\)數組,而後再相似\(KMP\)的匹配。
由於須要支持動態求前面一段區間有多少個數比這個數小,因此須要用\(BIT\)維護。數組
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<vector> using namespace std; #define ll long long #define MAX 1000100 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } vector<int> Ans; int c[MAX],N,n,m,a[MAX],S[MAX],p[MAX],nt[MAX],rk[MAX]; int lb(int x){return x&(-x);} void Add(int x,int w){while(x<=N)c[x]+=w,x+=lb(x);} int getsum(int x){int s=0;while(x)s+=c[x],x-=lb(x);return s;} int main() { n=read();m=read();N=n; for(int i=1;i<=n;++i)p[read()]=i; for(int i=1;i<=m;++i)S[i]=a[i]=read(); 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)Add(p[i],1),rk[i]=getsum(p[i]); memset(c,0,sizeof(c)); nt[0]=nt[1]=0; for(int i=2,lst=2;i<=n;++i) { int t=nt[i-1]; while(t&&getsum(p[i])+1!=rk[t+1]) { int v=nt[t]; while(lst<i-v)Add(p[lst++],-1); t=v; } if(getsum(p[i])+1==rk[t+1])++t; nt[i]=t;Add(p[i],1); } memset(c,0,sizeof(c));N=m; for(int i=1,j=0,lst=1;i<=m;++i) { while(j&&getsum(a[i])+1!=rk[j+1]) { int v=nt[j]; while(lst<i-v)Add(a[lst++],-1); j=v; } if(getsum(a[i])+1==rk[j+1])++j; if(j==n) { Ans.push_back(i-n+1);int v=nt[j]; while(lst<i-v+1)Add(a[lst++],-1); j=v; } Add(a[i],1); } printf("%d\n",(int)Ans.size()); for(int v:Ans)printf("%d ",v);puts(""); return 0; }