zoukankan      html  css  js  c++  java
  • luoguP4696 [CEOI2011]Matching KMP+树状数组

    可以非常轻易的将题意转化为有多少子串满足排名相同

    注意到$KMP$算法只会在当前字符串的某尾添加和删除字符

    因此,如果添加和删除后面的字符对于前面的字符没有影响时,我们可以用$KMP$来模糊匹配

    对于本题而言,在末尾插入一个字符时,如果$S$串和$T$串中这两个字符的排名一样,那么它们对前面的影响也是一样的

    因此,插入或者删除字符时,后面的字符如果排名一样,可以任何对前面没有影响

    反之,如果不一样,那么无法匹配

    所以,这满足模糊匹配的条件

    我们可以拿树状数组来维护插入和删除

    由于$next[i] leq next[i - 1] + 1$,因此分析一下复杂度不会超过$O(n log n)$

    好像带了大常数......

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    namespace remoon {
        #define ri register int
        #define rep(iu, st, ed) for(ri iu = st; iu <= ed; iu ++)
        #define drep(iu, ed, st) for(ri iu = ed; iu >= st; iu --)    
        #define gc getchar
        inline int read() {
            int p = 0, w = 1; char c = gc();
            while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
            while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
            return p * w;
        }
    }
    using namespace std;
    using namespace remoon;
    
    const int sid = 1005000;
    
    int n, m, cm, tot;
    int ans[sid], nxt[sid], pre[sid];
    int t[sid], p[sid], h[sid], T[sid];
    
    inline void upd(int o, int v) {
        for(ri i = o; i <= m; i += i & (-i)) 
            t[i] += v;
    }
    
    inline int qry(int o) {
        int ret = 0;
        for(ri i = o; i; i -= i & (-i))
            ret += t[i];
        return ret;
    }
    
    void Solve() {
        rep(i, 1, n)
            pre[i] = qry(p[i]), upd(p[i], 1);
        pre[n + 1] = -1;
            
        rep(i, 1, m) t[i] = 0;
        for(ri i = 2, j = 0; i <= n; i ++) 
        {
            while(j && qry(p[i]) != pre[j + 1]) 
            {
                for(ri k = i - j; k < i - nxt[j]; k ++) 
                    upd(p[k], -1);
                j = nxt[j];
            }
            if(qry(p[i]) == pre[j + 1]) j ++, upd(p[i], 1); 
            nxt[i] = j;
        }
        
        rep(i, 1, m) t[i] = 0;
        for(ri i = 1, j = 0; i <= m; i ++) 
        {
            while(j && qry(h[i]) != pre[j + 1]) 
            {    
                for(ri k = i - j; k < i - nxt[j]; k ++)
                    upd(h[k], -1);
                j = nxt[j];
            }
            if(qry(h[i]) == pre[j + 1]) j ++, upd(h[i], 1);
            if(j == n) ans[++ tot] = i - n + 1;
        }
    }
    
    int main() {
        
        n = read(); m = read();
        rep(i, 1, n) p[read()] = i;
        rep(i, 1, m) T[i] = h[i] = read();
        
        sort(T + 1, T + m + 1);
        cm = unique(T + 1, T + m + 1) - T - 1;
        rep(i, 1, m) h[i] = lower_bound(T + 1, T + cm + 1, h[i]) - T;
        
        Solve();
        printf("%d
    ", tot);
        rep(i, 1, tot) printf("%d ", ans[i]);
        printf("
    ");
        return 0;
    }
  • 相关阅读:
    虚方法、重写方法和抽象方法[转载]
    枚举的默认构造为第一个成员值!
    自定义Attribute例子!
    Python 处理MD5
    php5 反射refection 的用途
    python Sleep休眠函数
    python处理urlencode的两种方式
    python操作mysql进行更新的时候,必须有commit
    Python repr() 或str() 函数
    python抓取网页内容
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9949291.html
Copyright © 2011-2022 走看看