bzoj1461: 字符串的匹配

来源:互联网 发布:java pkcs10 公钥 编辑:程序博客网 时间:2024/06/15 11:36

传送门
首先我们记录B串中每个元素的排名信息
我记录了在他前面的比他小的数和相等的数的个数。
然后大力kmp(看毛片)
每一次跳next的术后记得删除无用元素。
因为加入是O(N)级别的
所以删除也是O(N)级别的。
然后大力kmp(再看毛片)
同样道理我们每一次跳next的术后记得删除无用元素。
为啥删除也是O(N)的也同上。
时间复杂度O(NlogN)

#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define N 500005#define M 10005using namespace std;int a[N],b[N],nxt[N],equ[N],les[N],ans[N];int tot,n,k,s,j,t[M];void add(int x,int d){    for (;x<=s;x+=x&(-x)) t[x]+=d;}int ask(int x){    int s=0;    for (;x;x-=x&(-x)) s+=t[x];    return s; }int main(){    scanf("%d%d%d",&n,&k,&s);    for (int i=1;i<=n;i++) scanf("%d",&a[i]);    for (int i=1;i<=k;i++){        scanf("%d",&b[i]);        add(b[i],1);        equ[i]=ask(b[i]);        les[i]=ask(b[i]-1);    }    memset(t,0,sizeof(t));    nxt[1]=j=0;    for (int i=2;i<=k;i++){        add(b[i],1);        while (j&&(ask(b[i])!=equ[j+1]||ask(b[i]-1)!=les[j+1])){            for (int k=i-j;k<i-nxt[j];k++) add(b[k],-1);            j=nxt[j];        }        if (ask(b[i])==equ[j+1]&&ask(b[i]-1)==les[j+1]) j++;        nxt[i]=j;    }    memset(t,0,sizeof(t));    j=0;    for (int i=1;i<=n;i++){        add(a[i],1);        while (j&&(ask(a[i])!=equ[j+1]||ask(a[i]-1)!=les[j+1])){            for (int k=i-j;k<i-nxt[j];k++) add(a[k],-1);            j=nxt[j];        }        if (j==k-1){            ans[++tot]=i-j;            for (int k=i-j;k<i-nxt[j];k++) add(a[k],-1);            j=nxt[j];        }        j++;    }    printf("%d\n",tot);    for (int i=1;i<=tot;i++) printf("%d\n",ans[i]);}
原创粉丝点击