poj 3167

来源:互联网 发布:linux 多进程 信号 编辑:程序博客网 时间:2024/04/29 00:39

好题啊

kmp+树状数组

可以加深 kmp的理解

在求next数组的时候 匹配条件不应该是 b[i]=b[j]吗 我们把他改成 我们体力所需要的条件 也就是rank[i]=rank[j] rank是什么呢就是当前数前面比他小的和和他相等的,只要跟模式串一样就ok
所以 就ok了

#include<cstdio>#include<algorithm>#include<cstring>#define maxn 1000005#define maxm 25005using namespace std;//by mars_chint next[maxm],pos[maxn];int s[maxn],eq[maxn];int a[maxn],b[maxm];int c[maxm];int n,k,S,all;int lowbit(int x){    return x&(-x);}void updata(int x,int y){    while(x<=S)    {        c[x]+=y;        x+=lowbit(x);    }}int sum(int x){    int res=0;    while(x)    {        res+=c[x];        x-=lowbit(x);    }    return res;}void getnext(){      int i=1,j=0,kk;      next[1]=0;      while(i<=k)    {          if(j==0 || (sum(b[i]-1)==s[j] && sum(b[i]) == eq[j]))        {              i++,j++;              next[i]=j;              if(i==k+1) return ;              updata(b[i],1);          }          else        {              for(kk=i-j+1;kk<=i-next[j];kk++)        //这里对next[j]之前的b[i]都要消除                  updata(b[kk],-1);              j=next[j];          }      }  }   int kmp(){    int i=1,j=1,f;      updata(a[1],1);      while(i<=n)    {          if(j==0 ||(sum(a[i]-1)==s[j] && sum(a[i])==eq[j]))        {              ++i,++j;              if(i<=n)                  updata(a[i],1);          }          else        {              for(f=i-j+1;f<=i-next[j];f++)                  updata(a[f],-1);              j=next[j];          }          if(j>k)        {              for(f=i-j+1;f<=i-next[j];f++)                  updata(a[f],-1);              all++;              pos[all]=i-1;              j=next[j];          }      }      return all;  }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]);        updata(b[i],1);        s[i]=sum(b[i]-1);        eq[i]=sum(b[i]);    }    memset(c,0,sizeof(c));    getnext();    memset(c,0,sizeof(c));    printf("%d\n",kmp());    for(int i=1;i<=all;i++)    {        printf("%d\n",pos[i]-k+1);    }}
0 0