zoukankan      html  css  js  c++  java
  • 【模板】字符串

    1 字符串 Hash

    const ll mod[3] = {900000011, 998244353, 1000000007};
    const ll bas[3] = {4493, 8111, 8527};
    // you can choose your bases and modulos
    
    char s[S];
    ll pw[3][S], Hash[3][S];
    
    inline ll getHash(int id, int L, int R){ // str[L..R-1]
        ll J = (Hash[id][R] - Hash[id][L] * pw[id][R - L]) % mod[id];
        return J < 0 ? J + mod[id] : J;
    }
    
    // following is the pretreatment
    ll *f, *g;
    for(j = 0; j < 3; j++){
        f = Hash[j]; f[0] = 0;
        g = pw[j]; g[0] = 1;
        for(i = 0; i < n; i++){
            f[i + 1] = (f[i] * bas[j] + (s[i] - 'a')) % mod[j];
            g[i + 1] = g[i] * bas[j] % mod[j];
        }
    }

    2 KMP 模式匹配

    // pretreatment (border) 
    for (j = *f = -1, i = 1; i < n; f[++i] = ++j)
        for (; ~j && s[j] != s[i]; j = f[j]);
    
    // KMP
    for (j = i = 0; i < _n; ++i) {
        for (; ~j && s[j] != m[i]; j = f[j]);
        if (++j == n) printf("%d ", i - s_n + 2);
    }

    3 字典树

    void append(char *s){
        char *p = s;
        int t = 1, id; // t = 0 is also OK
        for(; *p; ++p){
            id = *p - 97;
            t = d[t][id] ? d[t][id] : (d[t][id] = ++V);
        }
        ++val[t];
    }
    
    // the process of matching is just like going on a DFA, so omit it.

    4 Aho-Corasick 自动机

    void build(){
        int h, ta = 1, i, t, id;
        que[0] = 1;
        f[1] = 0;
        for(h = 0; h < ta; ++h)
            for(i = que[h], id = 0; id < 26; ++id){ // 26 is the size of char-set
                t = (f[i] ? d[f[i]][id] : 1); // 1 or 0 depend on the root of trie
                int &u = d[i][id];
                if(!u) {u = t; continue;}
                f[u] = t; val[u] |= val[t]; que[ta++] = u;
                la[u] = (v[t] ? t : la[t]);
            }
    }

    5 后缀数组 (倍增构造与最长公共前缀

    struct LCP {
        int n, *sa, *rnk, *st[LN];
        LCP () : n(0), sa(NULL), rnk(NULL) {memset(st, 0, sizeof st);}
        ~LCP () {
            if (sa) delete [] sa;
            if (rnk) delete [] rnk;
            for (int i = 0; i < LN; ++i) if (st[i]) delete [] st[i];
        }
        void construct(const char *s) {
            int i, j, k, m = 256, p, limit; n = strlen(s);
            int *x = new int[n + 1], *y = new int[n + 1], *buf = new int[max(n, m)], *f, *g = new int[n + 1];
            auto cmp = [this] (const int *a, const int u, const int v, const int l) {return a[u] == a[v] && (u + l >= n ? 0 : a[u + l]) == (v + l >= n ? 0 : a[v + l]);};
            if (sa) delete [] sa; sa = new int[n];
            if (rnk) delete [] rnk;
            for (i = 0; i < LN; ++i) if (st[i]) delete [] st[i], st[i] = 0;
            for (i = 0; i < n; ++i) sa[i] = i, x[i] = (unsigned char)s[i];
            std::sort(sa, sa + n, [s] (const int u, const int v) {return (unsigned char)s[u] < (unsigned char)s[v];});
            for (j = 1; j < n; j <<= 1, m = ++p) {
                std::iota(y, y + j, n - j), p = j;
                for (i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
                memset(buf, 0, m << 2);
                for (i = 0; i < n; ++i) ++buf[ x[y[i]] ];
                for (i = 1; i < m; ++i) buf[i] += buf[i - 1];
                for (i = n - 1; i >= 0; --i) sa[ --buf[ x[y[i]] ] ] = y[i];
                std::swap(x, y);
                x[*sa] = p = 1, x[n] = 0;
                for (i = 1; i < n; ++i) x[sa[i]] = (cmp(y, sa[i - 1], sa[i], j) ? p : ++p);
                if (p >= n) break;
            }
            if (rnk = x, n == 1) *x = 0;
            else for (i = 0; i < n; ++i) --x[i];
            delete [] buf, delete [] y;
            for (p = i = 0; i < n; ++i) {
                if (p && --p, !x[i]) continue;
                for (j = sa[x[i] - 1], limit = n - max(i, j); p < limit && s[i + p] == s[j + p]; ++p);
                g[ x[i] - 1 ] = p;
            }
            *st = g, k = n - 1;
            for (j = 0; 1 << (j + 1) < n; ++j) {
                k -= 1 << j, f = g, g = st[j + 1] = new int[k + 1];
                for (i = 0; i < k; ++i)
                    g[i] = min(f[i], f[i + (1 << j)]);
            }
        }
        inline int operator () (const int u, const int v) {
            assert((unsigned)u < (unsigned)n && (unsigned)v < (unsigned)n);
            if (u == v) return n - u;
            int L, R, c; std::tie(L, R) = std::minmax(rnk[u], rnk[v]), c = lg2(R - L);
            return min(st[c][L], st[c][R - (1 << c)]);
        }
    };

    6 后缀自动机

    #define q d[p][x]
    int extend(int x) {
        for (p = np, val[np = ++cnt] = val[p] + 1; p && !q; q = np, p = pa[p]);
        if (!p) pa[np] = 1;
        else if (val[p] + 1 == val[q]) pa[np] = q;
        else {
            int nq = ++cnt;
            val[nq] = val[p] + 1, memcpy(d[nq], d[q], 104);
            pa[nq] = pa[q], pa[np] = pa[q] = nq;
            for (int Q = q; p && q == Q; q = nq, p = pa[p]);
        }
        return f[np] = 1, np;
    }
    #undef q
     
    
    7 根据后缀自动机构造后缀树
    void build() {
        int i, j, c; used[1] = true;
        for (i = cnt; i; --i) if (~pos[i])
            for (j = i; !used[j]; j = pa[j])
                c = pos[j] - val[pa[j]], pos[pa[j]] = pos[j],
                child[pa[j]][int(s[c])] = j, used[j] = true;
    //    dfs(1);
    }

    8 Z 算法

    void Z() {
        int i, Max = 0, M = 0;
        for (i = 1; i < n; ++i) {
            z[i] = (i < Max ? std::min(z[i - M], Max - i) : 0);
            for (; s[z[i]] == s[i + z[i]]; ++z[i]);
            if (i + z[i] > Max) Max = i + z[i], M = i; 
        }
    }

    9 Manacher 回文串

    void Manacher() {
        int n = 2, i, Max = 0, M = 0;
        t[0] = 2, t[1] = 1;
        for (i = 0; i < S; ++i) t[n++] = s[i], t[n++] = 1; t[n++] = 3;
        for (i = 0; i < n; ++i){
            f[i] = (i < Max ? std::min(f[M * 2 - i], Max - i) : 1);
            for(; t[i + f[i]] == t[i - f[i]]; ++f[i]);
            if (i + f[i] > Max) Max = i + f[i], M = i;
        }
    }

    10 回文自动机

    int get_fail(int x) {for (; ptr[~val[x]] != *ptr; x = fail[x]); return x;}
    
    int extend(int x) {
        int &q = d[p = get_fail(p)][x];
        if (!q) fail[++cnt] = d[get_fail(fail[p])][x], val[q = cnt] = val[p] + 2;
        return p = q;
    }
    
    val[1] = -1, p = 0, *fail = cnt = 1;

    11 多串后缀自动机 / 广义后缀自动机

    #define q d[p][x]
    #define try_split(v) { 
        if (val[p] + 1 == val[q]) v = q; 
        else { 
            int nq = ++cnt; 
            val[nq] = val[p] + 1, memcpy(d[nq], d[q], 104); 
            pa[nq] = pa[q], v = pa[q] = nq; 
            for (int Q = q; p && q == Q; q = nq, p = pa[p]); 
        } 
    }
    
    int extend(int x) {
        if (p = np, q) try_split(np)
        else {
            for (val[np = ++cnt] = val[p] + 1; p && !q; q = np, p = pa[p]);
            if (p) try_split(pa[np]) else pa[np] = 1;
        }
        return np;
    }
    #undef q
  • 相关阅读:
    python习题一
    华为区块链平台
    百度超级链 [Xuperchain]
    $$$Fabric v1.0 block结构与修改
    搭建 Hyperladger Fabric 基本流程
    python开发区块链【公有链】
    Asp.Net中WebServices的调用方式
    关于vs08生成解决方案慢的解决方法
    vs项目启动调试时,显示找不到文件问题
    新的公司
  • 原文地址:https://www.cnblogs.com/lau1997/p/12665736.html
Copyright © 2011-2022 走看看