BZOJ 2384: [Ceoi2011]Match (KMP,树状数组)
这道题是 KMP 来转移子串中的相对排名.
然后查询排名的话需要用到树状数组.
如果跳 fail 指针的话要把没用元素全部删掉.
code:
#include <bits/stdc++.h> #define N 1005000 #define setI(s) freopen(s".in","r",stdin) using namespace std; int n,m,tot,cm; int ans[N],fail[N],pre[N]; int p[N],h[N],T[N]; namespace BIT { int t[N]; int lowbit(int x) { return x&(-x); } void update(int x,int v) { for(int i=x;i<=m;i+=lowbit(i)) t[i]+=v; } int query(int x) { int ret=0; for(int i=x;i;i-=lowbit(i)) ret+=t[i]; return ret; } void clr() { for(int i=0;i<N;++i) t[i]=0; } }; void calc() { BIT::clr(); for(int i=1;i<=n;++i) { pre[i]=BIT::query(p[i]); BIT::update(p[i],1); } pre[n+1]=-1; BIT::clr(); for(int i=2,j=0;i<=n;++i) { while(j&&BIT::query(p[i])!=pre[j+1]) { for(int k=i-j;k<i-fail[j];++k) BIT::update(p[k],-1); j=fail[j]; } if(BIT::query(p[i])==pre[j+1]) ++j,BIT::update(p[i],1); fail[i]=j; } BIT::clr(); for(int i=1,j=0;i<=m;++i) { while(j&&BIT::query(h[i])!=pre[j+1]) { for(int k=i-j;k<i-fail[j];++k) { BIT::update(h[k],-1); } j=fail[j]; } if(BIT::query(h[i])==pre[j+1]) { ++j; BIT::update(h[i],1); } if(j==n) ans[++tot]=i-n+1; } } int main() { // setI("input"); scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) { int x; scanf("%d",&x); p[i]=x; } for(int i=1;i<=m;++i) scanf("%d",&T[i]),h[i]=T[i]; sort(T+1,T+1+m); cm=unique(T+1,T+1+m)-T-1; for(int i=1;i<=m;++i) h[i]=lower_bound(T+1,T+1+cm,h[i])-T; calc(); printf("%d\n",tot); for(int i=1;i<=tot;++i) printf("%d ",ans[i]); printf("\n"); return 0; }