前缀树的相关算法(Java和C++实现)

前缀树的节点声明

public static class TrieNode{
		public int pass;
		public int end;
		public TrieNode[] nexts;  //一个节点连着那些字符
		
		public TrieNode() {
			pass = 0;
			end = 0;
			nexts = new TrieNode[26];  //定义26条路   a-z
			//当字符多种时的时候  可以使用map来进行描述 HashMap<Character, Node> nexts
		}
	}

定义一个root节点并声明

	private TrieNode root;
		public Trie() {
			root = new TrieNode();  //共用一个root节点
		}

插入

public void insert(String word) {
	if(word == null) return;
	char[] chs = word.toCharArray();
	TrieNode node = root;
	node.pass++;
	int index = 0;
	for(int i = 0; i < chs.length; i++) {
		index = chs[i] - 'a'; //判断该走那条路
		//判断有无路
		if(node.nexts[index] == null) {
			node.nexts[index] = new TrieNode();
		}
		node = node.nexts[index]; //移到这条路上
		node.pass++;
	}
	node.end++;
}

查询

//查询加入过几次
public int search(String word) {
	if(word == null) return 0;
	char[] chs = word.toCharArray();
	TrieNode node = root;
	int index = 0;
	for(int i = 0; i < chs.length; i++) {
		index = chs[i] - 'a';
		//即查到后面没路了  则返回0  例如之前加入的是abc  现在查询abcd的情况
		if(node.nexts[index] == null) return 0;
		node = node.nexts[index];
	}
	return node.end;
}

删除

public void delete(String word) {
	if(search(word) != 0) {
		char[] chs = word.toCharArray();
		TrieNode node = root;
		int index = 0;
		for(int i = 0; i < chs.length; i++) {
			index = chs[i] - 'a';
			//如果删除之后pass为0  则置为null
			if(--node.nexts[index].pass == 0) {
				node.nexts[index] = null;
				return;
			}
			node = node.nexts[index];
		}
		node.end--;
	}
}

主要是参考左神的算法 课程链接

C++实现

#include <iostream>

using namespace std;

const int N = 100010;
//cnt[i] 表示以i节点的单词个数 
//idx表示节点的下标  下标为0的既是根节点 又是空节点
int son[N][26], cnt[N], idx; 
char str[N];

void insert(char str[])
{
    int p = 0;
    for(int i = 0; str[i]; i++)
    {
        int u = str[i] - 'a';
        //p表示当前节点   u表示有没有路
        if(!son[p][u]) son[p][u] = ++idx;  //0为根节点  所以得先++
        p = son[p][u];  //转向下一个节点
    }
    
    cnt[p]++;
}

int query(char str[])
{
    int p = 0;
    for(int i = 0; str[i]; i++)
    {
        int u = str[i] - 'a';
        if(!son[p][u]) return 0;
        p = son[p][u];
    }
    
    return cnt[p];
}

int main()
{
    int n;
    char op;
    cin >> n;
    while(n--)
    {
        cin >> op >> str;
        if(op == 'I') insert(str);
        else cout << query(str) << endl;
    }
    return 0;
}

来源于AcwingTrie字符串统计

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值