3172: [Tjoi2013]单词 fail树

本文深入探讨了AC自动机与Trie树在字符串匹配和计数上的应用,通过构建Trie树并利用AC自动机的fail指针特性,实现高效地统计不同字符串的出现频率。详细介绍了算法实现步骤和优化技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先建一棵Trie,我们考虑AC自动机中fail指针的含义。
与KMP中的fail指针相似,它指向的位置代表了一个相同前后缀。所以我们首先给每个点打标记,即每个前缀(root->此点)都出现了一次,然后在构造完fail指针后,我们会发现fail指针反向后是一棵树 沿着fail指针扫一遍其实就是沿着树边向根扫一遍。只在插入时将每个串的每个节点sum++ 那么每个串终点所在fail树的子树中sum的总和就是这个字符串的出现次数,只要根据BFS序求和就好了。

据说这题的作法很多?

#include<bits/stdc++.h>
using namespace std;
char s[1000005];
int n,cnt=1,pos[222],a[1000005][26],sum[1000005],p[1000005],q[1000005];
inline void insert(int &pos)
{
    scanf("%s",s);
    int l=strlen(s),x=1,c;
    for (int i=0;i<l;i++)
    {
        c=s[i]-'a';
        if (a[x][c]) x=a[x][c]; else x=a[x][c]=++cnt;
        sum[x]++;
    }
    pos=x;
}
inline void build_fail()
{
    int t=0,w=1,x;
    q[1]=1; p[1]=0;
    while (t<w)
    {
        x=q[++t];
        for (int i=0;i<26;i++)
            if (a[x][i])
            {
                int k=p[x];
                while (!a[k][i]) k=p[k];
                p[a[x][i]]=a[k][i];
                q[++w]=a[x][i];
            }
    }
    for (int i=w;i;i--) sum[p[q[i]]]+=sum[q[i]];
}
int main()
{
    scanf("%d",&n);
    for (int i=0;i<26;i++) a[0][i]=1;
    for (int i=1;i<=n;i++) insert(pos[i]);
    build_fail();
    for (int i=1;i<=n;i++) printf("%d\n",sum[pos[i]]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值