码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2384

时间:2017-11-20 21:46:37      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:void   ++   问题   can   nlogn   scan   ++i   树状数组   oid   

树状数组+KMP

匹配问题上KMP

但是问题在于如何判断两个位置相等,我们认为如果一个位置之前比他小的数数量相同那么就是相等。

那么我们用树状数组动态维护这个东西,每次跳nxt的时候用树状数组删除数。因为每个数只加入一次,所以复杂度是nlogn的,为什么这样是对的呢?我们这么想,对于当前加入最后的一个字符,这个肯定是对的,如果我们再加入一个数,如果比这个数小,那么影响,否则不影响,现在两个串同时加入两个数,那么如果一个相对大一个相对小,那么这个位置肯定是不匹配的,所以即使影响了之前也没关系。大概是这样吧

技术分享图片
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e6 + 5;
int n, m;
int a[N], tree[N], s[N], v[N], b[N], c[N], nxt[N], ans[N];
void update(int x, int d)
{
    for(; x <= m; x += x & -x) tree[x] += d;
}
int query(int x)
{
    int ret = 0;
    for(; x; x -= x & -x) ret += tree[x];
    return ret;
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) scanf("%d", &a[i]), s[a[i]] = i;
    for(int i = 1; i <= n; ++i) v[i] = query(s[i]), update(s[i], 1);
    for(int i = 1; i <= m; ++i) scanf("%d", &b[i]), c[i] = b[i];
    memset(tree, 0, sizeof(tree));
    for(int i = 2, j = 0; i <= n; ++i)
    {
        while(query(s[i]) != v[j + 1]) 
        {
            for(int k = i - j; k < i - nxt[j]; ++k) update(s[k], -1);
            j = nxt[j];
        }
        if(query(s[i]) == v[j + 1])
        {
            update(s[i], 1);
            ++j;
        }
        nxt[i] = j;
    }
    sort(c + 1, c + m + 1);
    memset(tree, 0, sizeof(tree));
    for(int i = 1, j = 0; i <= m; ++i)
    {
        b[i] = lower_bound(c + 1, c + m + 1, b[i]) - c;
        while(j == n || query(b[i]) != v[j + 1])
        {
            for(int k = i - j; k < i - nxt[j]; ++k) update(b[k], -1);
            j = nxt[j];
        }
        if(query(b[i]) == v[j + 1])
        {
            ++j;
            update(b[i], 1);
        }
        if(j == n) ans[++ans[0]] = i - j + 1;
    }
    printf("%d\n", ans[0]);
    for(int i = 1; i <= ans[0]; ++i) printf("%d%c", ans[i], i == ans[0] ? \n :  );
    return 0;
}
View Code

 

bzoj2384

标签:void   ++   问题   can   nlogn   scan   ++i   树状数组   oid   

原文地址:http://www.cnblogs.com/19992147orz/p/7868097.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!