[ HAOI 2016 ] 找相同字元
阿新 • • 發佈:2021-07-14
題目
思路
程式碼
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 400010; int last = 1, tot = 1; int n, m, b[N], pos[N], sz[N]; long long f[N], res; string A, B; struct NODE { int len, link, ch[26]; } node[N]; void insert(int c) { int p = last, np = last = ++tot; node[np].len = node[p].len + 1, sz[np] = 1; for (; p && !node[p].ch[c]; p = node[p].link) node[p].ch[c] = np; if (!p) return node[np].link = 1, void(0); int q = node[p].ch[c]; if (node[q].len == node[p].len + 1) return node[np].link = q, void(0); int nq = ++tot; node[nq] = node[q], node[nq].len = node[p].len + 1; node[np].link = node[q].link = nq; for (; p && node[p].ch[c] == q; p = node[p].link) node[p].ch[c] = nq; } void topsort() { for (int i = 1; i <= tot; i++) b[node[i].len]++; for (int i = 1; i <= tot; i++) b[i] += b[i - 1]; for (int i = 1; i <= tot; i++) pos[b[node[i].len]--] = i; for (int i = tot; i >= 1; i--) sz[node[pos[i]].link] += sz[pos[i]]; for (int i = 2; i <= tot; i++) f[pos[i]] = 1ll * (node[pos[i]].len - node[node[pos[i]].link].len) * sz[pos[i]] + f[node[pos[i]].link]; } void match() { for (int i = 0, j = 1, k = 0; i < B.size(); i++) { int c = B[i] - 'a'; while (j && !node[j].ch[c]) j = node[j].link; if (!j) { j = 1, k = 0; continue; } k = min(k, node[j].len) + 1, j = node[j].ch[c]; res += f[node[j].link] + 1ll * (k - node[node[j].link].len) * sz[j]; } } signed main() { cin >> A >> B; for (int i = 0; i < A.size(); i++) insert(A[i] - 'a'); topsort(), match(); cout << res << endl; return 0; }