E. Tree-String Problem (AC自动机+fail树)

最后都变了- 提交于 2020-01-29 09:01:17

https://codeforces.com/problemset/problem/291/E
题意:给你一颗树,然后每一条边有一个字符串,然后给你一个字符串,问这个字符在所有的树的根到叶子结点练成的串中,出现了多少次。
做法:建立AC自动机,每个点进行计数,在对询问串建AC自动机时不需要计数,然后dfs遍历fail树进行计数就可以了。

#include "bits/stdc++.h"

using namespace std;
typedef long long ll;
const int maxn = 300000 + 10;
const ll mod = 1000000000 + 7;
#define lowbit(x) x&-x

int nxt[maxn][26], fail[maxn], sum[maxn], tot;
int modify(string s, int now, int f) {
    int len = s.size();
    for (int i = 0; i < len; i++) {
        int id = s[i] - 'a';
        if (nxt[now][id] == 0) nxt[now][id] = ++tot;
        now = nxt[now][id];
        if (f) sum[now]++;
    }

    return now;
}

void build() {
    queue<int> qu;
    for (int i = 0; i < 26; i++) {
        if (nxt[0][i] != 0) qu.push(nxt[0][i]);
    }
    while (!qu.empty()) {
        int u = qu.front();
        qu.pop();
        for (int i = 0; i < 26; i++) {
            if (nxt[u][i] != 0) fail[nxt[u][i]] = nxt[fail[u]][i], qu.push(nxt[u][i]);
            else nxt[u][i] = nxt[fail[u]][i];
        }
    }
}
struct node {
    int v, nxt;
    string s;
} ed[maxn];
int head[maxn], cnt, now;
void add(int u, int v, string ss) {
    ++cnt;
    ed[cnt].v = v;
    ed[cnt].nxt = head[u];
    ed[cnt].s = ss;
    head[u] = cnt;
}

void dfs(int u, int cnt) {
    for (int i = head[u]; i; i = ed[i].nxt) {
        string tmp = ed[i].s;
        int v = ed[i].v;
        int tt = modify(tmp, cnt, 1);
        dfs(v, tt);
    }
}
vector<int> g[maxn];

void dfs_cnt(int u) {
    for (auto x:g[u]) {
        dfs_cnt(x);
        sum[u] += sum[x];
    }
}

int n, m, fa;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> n;
    now = 0;
    string tt;
    for (int i = 2; i <= n; i++) {
        cin >> fa >> tt;
        add(fa, i, tt);
    }
    dfs(1, now);
    cin >> tt;
    int ans = modify(tt, 0, 0);
    build();
    for (int i = 1; i <= tot; i++) g[fail[i]].push_back(i);
    dfs_cnt(0);
    cout << sum[ans] << endl;
    return 0;
}


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!