进阶数据结构应用-单词

目录

题目-单词

问题分析

目标是每个单词出现的次数, 分为两类

  • 如果当前单词不是某个单词子串, 那么出现次数是 1 1 1
  • 如果当前单词是某个单词的子串, 如何计算次数?

我们可以统计这样一个数值, 对于串 s s s, 有多少个前缀是以 s s s为后缀的 , 这个值就是答案

对于字符串 t t t, 某一个前缀的后缀 是 s s s, 那么答案需要累计

如何计算?

对于当前串 s s s, 计算当前后缀 和哪些前缀匹配, 在AC自动机直接可以迭代计算

fail[u], fail[fail[u]], fail[fail[fail[u]]]...都是和当前后缀匹配的前缀

递推思想, 对于当前后缀出现次数 假设是 x x x, 将前面的前缀全部累加 + x +x +x

例如某个后缀是aaa, 与之匹配的aa前缀也需要 + 1 +1 +1, 与aa匹配的前缀a也需要 + 1 +1 +1

因此直接按照AC自动机的fail指针拓扑序逆序递推就能得到答案

算法步骤

  • 将读入的字符串加入到Trie中, 假设当前遍历的是节点 u u u, u u u作为后缀出现次数累加cnt[u]++
  • 假设当前添加的是第 k k k个字符串, 当字符串添加完毕后, 记录结尾的Trie指针id[k] = u
  • 构建AC自动机
  • 按照拓扑序逆序从后向前递推 , 因为后面的是更长的后缀 , cnt[fail[i]] += cnt[i]
  • 按照 i d id id计算每个字符串出现的次数

代码实现

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

const int N = 210, M = 1e6 + 10;

int n;
int tr[M][26], idx;
int f[M];
int q[M], h, t;
int fail[M], id[N];

void insert(string &s, int k) {
    int p = 0;
    for (int i = 0; s[i]; ++i) {
        int c = s[i] - 'a';
        if (!tr[p][c]) tr[p][c] = ++idx;
        p = tr[p][c];
        // 因为p是代表某个后缀, 因此需要在p = tr[p][c]后面f[p]++
        f[p]++;
    }

    id[k] = p;
}

void build() {
    h = 0, t = -1;
    for (int i = 0; i < 26; ++i) {
        if (tr[0][i]) q[++t] = tr[0][i];
    }

    while (h <= t) {
        int u = q[h++];
        for (int i = 0; i < 26; ++i) {
            int v = tr[u][i];
            if (!v) continue;
            int j = fail[u];
            while (j && !tr[j][i]) j = fail[j];
            if (tr[j][i]) j = tr[j][i];
            fail[v] = j;
            q[++t] = v;
        }
    }
}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n;
    string s;
    for (int i = 0; i < n; ++i) {
        cin >> s;
        insert(s, i);
    }

    build();

    for (int i = t; i >= 0; --i) {
        int u = q[i];
        f[fail[u]] += f[u];
    }

    for (int i = 0; i < n; ++i) cout << f[id[i]] << '\n';

    return 0;
}
相关推荐
计算机安禾1 小时前
【C语言程序设计】第37篇:链表数据结构(一):单向链表的实现
c语言·开发语言·数据结构·c++·算法·链表·蓝桥杯
皮卡狮2 小时前
高阶数据结构:AVL树
数据结构·算法
不要秃头的小孩2 小时前
50. 随机数排序
数据结构·python·算法
故事和你913 小时前
sdut-python-实验四-python序列结构(21-27)
大数据·开发语言·数据结构·python·算法
丶小鱼丶4 小时前
数据结构和算法之【栈】
java·数据结构
不要秃头的小孩4 小时前
力扣刷题——111.二叉树的最小深度
数据结构·python·算法·leetcode
散峰而望4 小时前
【基础算法】从入门到实战:递归型枚举与回溯剪枝,暴力搜索的初级优化指南
数据结构·c++·后端·算法·机器学习·github·剪枝
汉克老师4 小时前
GESP2026年3月认证C++三级( 第一部分选择题(9-15))
c++·字符串·数组长度·反码·枚举算法·gesp三级·gesp3级
A923A5 小时前
【洛谷刷题 | 第五天】
算法·字符串·递归·洛谷
elseif1236 小时前
CSP-S提高级大纲
开发语言·数据结构·c++·笔记·算法·大纲·考纲