• 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;
    }
  • 相关阅读:
    CodeForces 156B Suspects(枚举)
    CodeForces 156A Message(暴力)
    CodeForces 157B Trace
    CodeForces 157A Game Outcome
    HDU 3578 Greedy Tino(双塔DP)
    POJ 2609 Ferry Loading(双塔DP)
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛十六进制转换成十进制
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9949291.html
Copyright © 2020-2023  润新知