BZOJ 1461 && BZOJ 1729
KMP+BIT
一看就是字符串匹配但是不同的是要按照每个字符的排名情况。
首先对于数字x的排名,那么要判断x前小于x的数的个数,和x前小于等于x的数的个数,这两个都相等才相等。因为会有数字会有重复的.
然后可以先预处理出字串的每个数字的排名,这样就不需要两个BIT了。最后按照KMP的思路做就可以了.
1 #include <cstdio> 2 #include <cstring> 3 const int MaxN=500100; 4 const int MaxS=10010; 5 int a[MaxN],b[MaxN],Rk1[MaxN],Rk2[MaxN],Ans[MaxN],tot,n,k,s,P[MaxN]; 6 int c[MaxS]; 7 inline int Lowbit(int x) {return x&-x;} 8 inline void Add(int x,int d) 9 {for (int i=x;i<=s;i+=Lowbit(i)) c[i]+=d;} 10 inline int Query(int x) 11 { 12 int Ret=0; 13 for (int i=x;i;i-=Lowbit(i)) Ret+=c[i]; 14 return Ret; 15 } 16 int main() 17 { 18 scanf("%d%d%d",&n,&k,&s); 19 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 20 for (int i=1;i<=k;i++) 21 { 22 scanf("%d",&b[i]); Add(b[i],1); 23 Rk1[i]=Query(b[i]),Rk2[i]=Query(b[i]-1); 24 } 25 memset(c,0,sizeof(c)); int j=0; 26 for (int i=2;i<=k;i++) 27 { 28 Add(b[i],1); 29 while (j && ((Query(b[i])!=Rk1[j+1]) || (Query(b[i]-1)!=Rk2[j+1]))) 30 { 31 for (int l=i-j;l<i-P[j];l++) Add(b[l],-1); 32 j=P[j]; 33 } 34 if ((Query(b[i])==Rk1[j+1]) && (Query(b[i]-1)==Rk2[j+1])) j++; 35 P[i]=j; 36 } 37 memset(c,0,sizeof(c)); j=0; 38 for (int i=1;i<=n;i++) 39 { 40 Add(a[i],1); 41 while (j && (Query(a[i])!=Rk1[j+1] || Query(a[i]-1)!=Rk2[j+1])) 42 { 43 for (int l=i-j;l<i-P[j];l++) Add(a[l],-1); 44 j=P[j]; 45 } 46 if (Query(a[i])==Rk1[j+1] && Query(a[i]-1)==Rk2[j+1]) j++; 47 if (j==k) 48 { 49 Ans[++tot]=i-j+1; 50 for (int l=i-j+1;l<=i-P[j];l++) Add(a[l],-1); 51 j=P[j]; 52 } 53 } 54 printf("%d\n",tot); 55 for (int i=1;i<=tot;i++) printf("%d\n",Ans[i]); 56 return 0; 57 58 }