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

【模板】字符串

时间:2020-04-09 12:22:45      阅读:62      评论:0      收藏:0      [点我收藏+]

标签:min   void   sed   回文串   man   asi   like   turn   mat   

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

 

【模板】字符串

标签:min   void   sed   回文串   man   asi   like   turn   mat   

原文地址:https://www.cnblogs.com/lau1997/p/12665736.html

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