BZOJ 1461: 字符串的匹配 kmp套树状数组

《BZOJ 1461: 字符串的匹配 kmp套树状数组》

《BZOJ 1461: 字符串的匹配 kmp套树状数组》

《BZOJ 1461: 字符串的匹配 kmp套树状数组》

《BZOJ 1461: 字符串的匹配 kmp套树状数组》

《BZOJ 1461: 字符串的匹配 kmp套树状数组》

《BZOJ 1461: 字符串的匹配 kmp套树状数组》

解法:这题就是kmp匹配过程中用树状数组维护每个数字出现的次数,快速查询在前面比自己小的和等于自己的来判断是否能向后匹配

///BZOJ 1461
///KMP + BIT

#include <bits/stdc++.h>
using namespace std;
const int maxn = 500010;
const int maxs = 10010;
int n, k, s;
int a[maxn], b[maxn], fail[maxn];
int rnk1[maxn], rnk2[maxn];
vector <int> ans;
int c[maxn];
inline int lowbit(int x){return x&-x;}
inline void add(int x, int v){for(int i=x; i<=s; i+=lowbit(i)) c[i]+=v;}
inline int query(int x){
    if(x==0) return 0;
    int ret = 0;
    for(int i=x; i; i-=lowbit(i)) ret += c[i];
    return ret;
}
inline void kmp(){

}

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), rnk1[i]=query(b[i]), rnk2[i]=query(b[i]-1);
    int i, j, m;
    fail[1]=j=0;
    memset(c, 0, sizeof(c));
    for(int i=2; i<=k; i++){
        add(b[i], 1);
        while(j&&(query(b[i])!=rnk1[j+1]||query(b[i]-1)!=rnk2[j+1])){
            for(m=i-j; m<i-fail[j]; m++) add(b[m],-1);
            j=fail[j];
        }
        fail[i] =j+=(query(b[i])==rnk1[j+1]) && (query(b[i]-1)==rnk2[j+1]);
    }
    j = 0;
    memset(c, 0, sizeof(c));
    for(int i=1; i<=n; i++){
        add(a[i], 1);
        while(j&&(query(a[i])!=rnk1[j+1]||query(a[i]-1)!=rnk2[j+1])){
            for(m=i-j; m<i-fail[j]; m++) add(a[m],-1);
            j=fail[j];
        }
        if(j==k-1){
            ans.push_back(i-j);
            for(m=i-j; m<i-fail[j]; m++) add(a[m],-1);
            j=fail[j];
        }
        ++j;
    }
    int tot = ans.size();
    printf("%d\n", tot);
    for(int i=0; i<tot; i++){
        printf("%d\n", ans[i]);
    }
    return 0;
}
    原文作者:KMP算法
    原文地址: https://blog.csdn.net/just_sort/article/details/71183185
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞