BZOJ_P1461 字符串的匹配(KMP+树状数组)

10 篇文章 0 订阅
6 篇文章 0 订阅

BZOJ传送门
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 180 Solved: 91
[Submit][Status][Discuss]
Description
这里写图片描述

Input
这里写图片描述

Output
这里写图片描述

Sample Input
这里写图片描述

Sample Output
这里写图片描述

HINT
这里写图片描述

Source

KMP+树状数组统计排名

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define N 500005
#define M 10005
int a[N],b[N],rk1[N],rk2[N],f[N],ans[N];int c[M];
int n,m,s,t;
inline int in(int x=0,char ch=getchar()){
    while(ch>'9'||ch<'0') ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x;
}
inline int lowbit(int x){return x&(-x);}
inline void add(int x,int v){while(x<=s) c[x]+=v,x+=lowbit(x);}
inline int sum(int x,int res=0){while(x) res+=c[x],x-=lowbit(x);return res;}
int main(){
    n=in(),m=in(),s=in();
    for(int i=0;i<n;i++) a[i]=in();
    for(int i=0;i<m;i++) b[i]=in(),add(b[i],1),rk1[i]=sum(b[i]-1),rk2[i]=sum(b[i]);
    memset(c,0,sizeof(c));
    for(int i=1,j;i<m;i++){
        j=f[i];add(b[i],1);
        while(j&&(sum(b[j]-1)!=rk1[i]||sum(b[j])!=rk2[i])){
            for(int p=i-j;p<i-f[j];p++) add(b[p],-1);
            j=f[j];
        }
        f[i+1]=(rk1[j]==sum(b[i]-1)&&rk2[j]==sum(b[i]))?j+1:0;
    }
    memset(c,0,sizeof(c));
    for(int i=0,j=0;i<n;i++){
        add(a[i],1);
        while(j&&(sum(a[i]-1)!=rk1[j]||sum(a[i])!=rk2[j])){
            for(int p=i-j;p<i-f[j];p++) add(a[p],-1);
            j=f[j];
        }
        if(sum(a[i]-1)==rk1[j]&&sum(a[i])==rk2[j]) j++;
        if(j==m){
            ans[++t]=i-j+1;
            for(int p=i-j+1;p<=i;p++) add(a[p],-1);
            j=0;
        }
    }
    printf("%d\n",t);
    for(int i=1;i<=t;i++) printf("%d\n",ans[i]+1);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值