zoukankan      html  css  js  c++  java
  • bzoj2384

    树状数组+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
    ", ans[0]);
        for(int i = 1; i <= ans[0]; ++i) printf("%d%c", ans[i], i == ans[0] ? '
    ' : ' ');
        return 0;
    }
    
    View Code
  • 相关阅读:
    python装饰器的作用
    python的__call__、__str__、__repr__、__init__、__class__、__name___、__all__、__doc__、__del__等魔术方法的作用
    安全小测试:介绍一个简单web安全知识测试的网站
    浏览器都知道我们的哪些信息?
    SQL开发技巧(二)
    如何解决SQLServer占CPU100%
    记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题
    如何在SQLServer中处理每天四亿三千万记录
    SqlServer索引的原理与应用
    T-sql语句查询执行顺序
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7868097.html
Copyright © 2011-2022 走看看