String

roychuang

Trie

Trie

Trie

vector<array<int, 26>> trie(MAXN, array<int, 26> {});
vector<bool> is_end(MAXN, false);
int it = 1;

Code

void insert(string &s) {
	int cur = 0;
	for (char c : s) {
    	if (trie[cur][c-'a'] == 0) {
        	trie[cur][c-'a'] = it++;
        }
        cur = trie[cur][c-'a'];
    }
    is_end[cur] = true;
}
void dfs(int cur) {
	for (int i = 0; i < 26; i++) if (trie[cur][i] != 0) {
    	dfs(trie[cur][i]);
    }
    // Example
    cout << cur << endl;
}

Trie

Problems

Hash

Hash

Hash

Code

using lli = long long int;
 
lli fpow(lli a, lli p, lli m) {
        lli res = 1;
        while (p) {
                if (p & 1) res = (res * a) % m;
                a = (a * a) % m;
                p >>= 1;
        }
        return res;
}
 
lli inv(lli a, lli p) {
        return fpow(a, p-2, p);
}
 
const lli hash_mod = 998244353;
const lli hash_mul = 257;
 
struct HashString {
        int N;
        vector<lli> h; // h[i] = hash([0...i])
        HashString(string S) : N(SZ(S)), h(N) {
                lli pre_mul = 1, last_hash = 0;
                for (int i = 0; i < N; i++) {
                        h[i] = (last_hash + S[i] * pre_mul) % hash_mod;
                        pre_mul = (pre_mul * hash_mul) % hash_mod;
                        last_hash = h[i];
                }
        }
        lli all() {
                return h[N-1];
        }
        lli get_hash(int l, int r) {
                if (l == 0) return h[r];
                lli hash = h[r];
                if (hash > h[l-1]) hash -= h[l-1];
                else               hash = hash + hash_mod - h[l-1];
                lli div_inv = inv(fpow(hash_mul, l, hash_mod), hash_mod);
                hash = (hash * div_inv) % hash_mod;
                return hash;
        }
};

Hash

Problems

KMP

Knuth–Morris–Pratt

KMP

KMP

Code

vector<int> KMP(string s) {
        int N = SZ(s);
        vector<int> pi(N);
        pi[0] = 0;
        for (int i = 1; i < N; i++) {
                int j = pi[i - 1];
                while (j > 0 and s[i] != s[j]) j = pi[j - 1];
                if (s[i] == s[j]) j++;
                pi[i] = j;
        }
        return pi;
}

KMP

Problems

Z

Z

Z

Code

vector<int> z_function(string s) {
        int N = SZ(s);
        vector<int> z(N);
        z[0] = 0;
        int L = 0, R = 0;
        for (int i = 1; i < N; i++) {
                if (i <= R and z[i - L] < R - i + 1) {
                        z[i] = z[i - L];
                } else {
                        z[i] = max(0, R - i + 1);
                        while (i + z[i] < N and s[ z[i] ] == s[ i + z[i] ]) {
                                z[i]++;
                        }
                        if (i + z[i] - 1 > R) {
                                L = i;
                                R = i + z[i] - 1;
                        }
                }
        }
        return z;
}

Z

Problems

KMP <=> Z

KMP <=> Z

Z -> KMP

for (int i = 1; i < n; i++) {
    if (z[i] > 0) F[i + z[i] - 1] = max(F[i + z[i] - 1], z[i]);
}

for (int i = n - 2; i >= 0; i--) {
    F[i] = max(F[i + 1] - 1, F[i]);
}

KMP <=> Z

for (int i = 1; i < n; i++) {
    if (F[i] > 0) z[i - F[i] + 1] = max(z[i - F[i] + 1], F[i]);
}

for (int i = 1; i < n;) {
    int j = 1, val;
    while (j < z[i]) {
        val = min(z[j], z[i] - j);
        if (val < z[i + j]) {
            break;
        }
        z[i + j] = val;
        j++;
    }
    i += j;
}

Manacher

Manacher

Code

vector<int> manacher(string &s) {
        int N = SZ(s);
        vector<int> m(N);
        m[0] = 0;
        int L = 0, R = 0;
        for (int i = 1; i < N; i++) {
                if (i <= R and m[L + L - i] < R - i) {
                        m[i] = m[L + L - i];
                } else {
                        m[i] = max(0, R - i);
                        while (m[i] < i and i + m[i] + 1 < N and s[i + m[i] + 1] == s[i - m[i] - 1]) {
                                m[i]++;
                        }
                        if (i + m[i] > R) {
                                L = i;
                                R = i + m[i];
                        }
                }
        }
        return m;
}

Manacher

Manacher

Problems

AC Automaton

Aho-Corasick

AC Automaton

Code

struct Aho_Corasick {
        vector<vector<int>> trie;
        vector<int> fail;
        vector<bool> is_end;
        vector<int> str_to_id;
        vector<vector<int>> dfs_adj;
        vector<int> dp;
        int it; // point to the end of the trie
 
        Aho_Corasick(int MAXN) :
                trie(MAXN, vector<int> (26, -1)),
                fail(MAXN, 0),
                is_end(MAXN, 0),
                str_to_id(MAXN),
                dfs_adj(MAXN),
                dp(MAXN, 0),
                it(0)
        {}
 
        void insert(string &t, int str_id) { // build trie
                int cur = 0;
                for (const char c : t) {
                        int j = c - 'a';
                        if (trie[cur][j] == -1) {
                                trie[cur][j] = ++it;
                        }
                        cur = trie[cur][j];
                }
                is_end[cur] = 1;
                str_to_id[str_id] = cur;
        }
 
        void bfs() {
                queue<int> qu;
                for (int j = 0; j < 26; j++) {
                        if (trie[0][j] != -1) {
                                qu.push(trie[0][j]);
                                dfs_adj[0].eb(trie[0][j]);
                        } else {
                                trie[0][j] = 0; // fail edge
                        }
                }
                while (not qu.empty()) {
                        int cur = qu.front(); qu.pop();
                        for (int j = 0; j < 26; j++) {
                                int &nxt = trie[cur][j];
                                if (nxt != -1) {
                                        int link_to = trie[fail[cur]][j];
                                        fail[nxt] = link_to;
                                        dfs_adj[link_to].eb(nxt);
                                        qu.push(nxt);
                                } else {
                                        nxt = trie[fail[cur]][j];
                                }
                        }
                }
        }
 
        void dfs(int cur) {
                for (const int &nxt : dfs_adj[cur]) {
                        dfs(nxt);
                        dp[cur] += dp[nxt];
                }
        }
 
        void traverse(string &t) {
                int cur = 0;
                for (const char &c : t) {
                        cur = trie[cur][c-'a'];
                        dp[cur]++;
                }
        }
};

AC Automaton

Problems

AC Automaton

Thanks

String

By Roy Chuang

String

  • 80