trie 字典树

本文详细介绍了如何使用C++实现Trie Tree(字典树),用于高效匹配和存储字符串。通过实例演示了从初始化到字符串插入、搜索等操作的全过程,并通过代码示例展示了具体实现。

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

const int sigm_size=26;
const int maxnode=400000+5;
int sz; //结点
int ch[maxnode][sigm_size],val[maxnode];

int idx(char c)
{
    return c-'a';
}

void init()
{
    sz=1;
    memset(ch[0],0,sizeof(ch[0]));//初始化根结点
}

void trie(char *s,int v)
{
    int c,i,j,u=0,n=strlen(s);
    for(i=0;i<n;i++)
    {
        c=idx(s[i]);
        if(!ch[u][c])//结点不存在
        {
            memset(ch[sz],0,sizeof(ch[sz]));
            val[sz]=0;
            ch[u][c]=sz++;//新建结点
        }
        u=ch[u][c];//往下走
    }
    val[u]=v;//字符串最后一个字符的附加信息
}

指针写法

#include<bits/stdc++.h>
using namespace std;
struct trie
{
    int cnt,num;
    int id;
    trie *son,*bro;
};

trie *rt=new trie;
int tot;
void settrie(char *s,int j)
{
    trie *p=rt,*t,*t1;
    int n=strlen(s),i,c;
    for(i=0; i<n; i++)
    {
        c=s[i]-'a';
        while(p->num!=-1&&p->num!=c)
        {
            t=p;
            p=p->bro;
            if(p->num>c)
            {
                p=t;
                break;
            }
        }
        //if(i==0&&c==3) printf("%d\n",++tot);
        if(p->num==-1)
        {
            p->cnt=1;
            p->num=c;
            t= new trie;
            t->id=-1;
            t->num=-1;
            t->cnt=0;
            p->bro=t;

            t= new trie;
            t->num=-1;
            t->cnt=0;
            t->id=-1;
            p->son=t;

            p->id=j;
            p=p->son;
        }
        else if(p->num==c)
        {
            if(p->id!=j) p->cnt++;
            p->id=j;
            p=p->son;
        }
        else
        {
            t= new trie;
            t->num=c;
            t->cnt=1;
            t->id=-1;
            t1= new trie;
            t1->id=-1;
            t1->num=-1;
            t1->cnt=0;
            t->son=t1;
            t->bro=p->bro;
            p->bro=t;
            p=t;
            p->id=j;
            p=p->son;
        }
    }
}


int main()
{
    int ans,c,n,i,j,len;
    char s[50];
    trie *p,*t;
    while(~scanf("%d",&n))
    {
        rt=new trie;
        rt->num=-1;
        rt->cnt=0;
        rt->id=-1;
        tot=0;
        for(i=0; i<n; i++)
        {
            scanf("%s",s);
            len=strlen(s);
            for(j=0; j<len; j++)
                settrie(s+j,i);
        }
        scanf("%d",&n);
        for(i=0; i<n; i++)
        {
            scanf("%s",s);
            len=strlen(s);
            p=rt;
            ans=0;
            for(j=0; j<len; j++)
            {
                c=s[j]-'a';
                while(p->num!=-1&&p->num!=c)
                {
                    t=p;
                    p=p->bro;
                    if(p->num>c)
                    {
                        p=t;
                        break;
                    }
                }
                if(p->num==c)
                {
                    ans=p->cnt;
                    p=p->son;
                }
                else break;
            }
            if(j!=len) ans=0;
            printf("%d\n",ans);
        }
    }
    return 0;
}
### 使用Trie字典树进行敏感词检测的实现方法 #### 背景介绍 Trie字典树是一种高效的树形数据结构,广泛应用于字符串处理领域。它通过共享公共前缀的方式减少了存储空间和查询时间,在敏感词检测场景下表现尤为突出[^1]。 #### 数据结构设计 Trie树的核心在于其节点的设计。每个节点通常包含以下几个部分: - **字符**:当前节点所代表的字符。 - **子节点集合**:指向下一个可能的字符节点。 - **结束标志位 (isEnd)**:用于标记某个路径是否构成了完整的敏感词[^2]。 以下是Trie节点的一个简单定义: ```java class TrieNode { private boolean isEnd; private Map<Character, TrieNode> children; public TrieNode() { this.children = new HashMap<>(); this.isEnd = false; } public boolean isEnd() { return isEnd; } public void setEnd(boolean end) { isEnd = end; } public Map<Character, TrieNode> getChildren() { return children; } } ``` #### 插入敏感词 为了构建一棵能够完成敏感词检测的Trie树,首先需要将所有的敏感词插入到树中。每插入一个新词时,按照字母顺序逐层创建节点并更新`isEnd`属性以标记完整词语的位置[^3]。 示例代码如下所示: ```java public class Trie { private final TrieNode root; public Trie() { root = new TrieNode(); } // 向Trie树中添加一个新的敏感词 public void addWord(String word) { TrieNode current = root; for (char c : word.toCharArray()) { if (!current.getChildren().containsKey(c)) { current.getChildren().put(c, new TrieNode()); } current = current.getChildren().get(c); } current.setEnd(true); // 设置最后一个节点为终止状态 } } ``` #### 进行敏感词过滤 当完成了所有敏感词的初始化之后,就可以基于这棵Trie树来进行实际的文字审查工作了。具体做法是从输入文本的第一位开始逐步向下匹配直到找到整个句子或者遇到未记录下来的分支为止[^2]。 下面给出了一段Java程序片段展示如何替换掉原文中的不当表述部分: ```java public String filter(String text) { StringBuilder sb = new StringBuilder(); int length = text.length(); for(int i=0;i<length;){ int j=i; TrieNode node=root; while(j<length && node!=null){ char ch=text.charAt(j); node=node.getChildren().get(ch); if(node==null || !node.isEnd()){ break; } if(node.isEnd()){ sb.append("***"); i=j+1; continue; } j++; } if(i>=j){ sb.append(text.charAt(i)); i++; }else{ i=j; } } return sb.toString(); } ``` 此函数会逐一扫描给定字符串里的每一项成分,并依据预先建立好的规则决定保留原样还是替换成指定符号序列(这里选用的是三个星号)。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值