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

来源:互联网 发布:dns协议使用什么端口 编辑:程序博客网 时间:2024/06/04 19:50

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

解法:这题就是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;}
0 0
原创粉丝点击