字典树(查找树)入门

字典树

树状结构保存字符串,查找快,判断前缀快。
又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。

例题: link.
代码(指针)
#include <iostream>
#include <cstdio>
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
// #include <unordered_set>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
#define T int T;scanf("%d",&T);while(T--)
const ll mod=1e6+3;
const int maxn = 1e5+5;
struct Trie{
	int num;		//到这个节点为前缀的单词个数
	Trie *nxt[30];		//指向26个字母
};
Trie *root;		//根结点不放字母
void init(Trie *p){
	for(int i = 0; i < 30; i++)
		p->nxt[i]=NULL;
	p->num = 0;
}
void insert(string s){
	Trie *cnt = root;	//从根结点开始遍历
	int len = s.size();
	for(int i = 0; i < len; i++){
		int id = s[i]-'a';	
		if(cnt->nxt[id]==NULL){		//如果当前节点下面没有第i个字母,就添加新节点;
			Trie *p = new Trie();
			// init(p);
			cnt->nxt[id] = p;
		}
		cnt = cnt->nxt[id];		//更新节点位置
		cnt->num++;		//前缀+1
	}
}
int find(string s){
	Trie *cnt = root;	//从根节点开始找
	int len = s.size();
	int ans = 0;
	for(int i = 0; i < len; i++){
		int id = s[i]-'a';
		if(cnt->nxt[id]==NULL) return 0;	//如果找不到,以s为前缀的单纯数为0
		cnt = cnt->nxt[id];		
		ans = cnt->num;		//更新值
	}
	return ans;
}
int main(){
	root = new Trie();
	// cout << root->nxt[1] << endl;
	// init(root);
	string s;
   	while(getline(cin,s)){		//输入单词
   		if(s=="") break;	
   		insert(s);
   	}

   	while(cin >> s){
   		int ans = find(s);	//统计以s为前缀的单词数量
   		cout << ans << endl;
   	}

    return 0;
}
/*
7
bababa
band
bee
absolute
absord
acm
beer


*/
代码(数组)
#include <iostream>
#include <cstdio>
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include<sstream>
// #include <unordered_set>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define pb push_back
#define T int T;scanf("%d",&T);while(T--)
const ll mod=1e9+7;
const int maxn = 2e6+5;
int trie[maxn][30];
int sum[maxn];
int cnt;
int n,k;
void insert(string s){
    int root=0;
    for(int i = 0; i < s.size(); i++){
        int id=s[i]-'a';
        if(trie[root][id]==0){
            trie[root][id]=++cnt;
        }
        sum[trie[root][id]]++;
        root=trie[root][id];
    }
    // vis[root]=1;
}
int find(string s){
    int ans = 0;
    int root=0;
    for(int i = 0; i < s.size(); i++){
        int id=s[i]-'a';
        if(trie[root][id]==0) return 0;
        ans = sum[trie[root][id]];
        root = trie[root][id];
    }
    return ans;
    // return !vis[root];
}
int main(){
    string s;
    while(getline(cin,s)){      //输入单词
        if(s=="") break;    
        insert(s);
    }
    while(cin >> s){
        int ans = find(s);  //统计以s为前缀的单词数量
        cout << ans << endl;
    }

    return 0;
}
/*
5 6 2
1 1 2 5 2

5 6 2
1 1 1 5 2

*/
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值