[ HAOI 2016 ] 找相同字符

题目

Luogu
LOJ
Acwing

思路

001.png

代码

#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;
}
posted @ 2021-07-14 19:16  Protein_lzl  阅读(40)  评论(0编辑  收藏  举报