hihocoder #1014 : Trie树

本文介绍了一个关于Trie树的应用案例,通过构建Trie树快速查找词典中以指定字符串为前缀的所有单词。文章详细解释了Trie树的创建过程及如何利用Trie树高效地解决字符串匹配问题。

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

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。

这一天,他们遇到了一本词典,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能对于每一个我给出的字符串,都在这个词典里面找到以这个字符串开头的所有单词呢?

身经百战的小Ho答道:“怎么会不能呢!你每给我一个字符串,我就依次遍历词典里的所有单词,检查你给我的字符串是不是这个单词的前缀不就是了?

小Hi笑道:“你啊,还是太年轻了!~假设这本词典里有10万个单词,我询问你一万次,你得要算到哪年哪月去?”

小Ho低头算了一算,看着那一堆堆的0,顿时感觉自己这辈子都要花在上面了...

小Hi看着小Ho的囧样,也是继续笑道:“让我来提高一下你的知识水平吧~你知道树这样一种数据结构么?”

小Ho想了想,说道:“知道~它是一种基础的数据结构,就像这里说的一样!”

小Hi满意的点了点头,说道:“那你知道我怎么样用一棵树来表示整个词典么?”

小Ho摇摇头表示自己不清楚。

提示一:Trie树的建立

“你看,我们现在得到了这样一棵树,那么你看,如果我给你一个字符串ap,你要怎么找到所有以ap开头的单词呢?”小Hi又开始考校小Ho。

“唔...一个个遍历所有的单词?”小Ho还是不忘自己最开始提出来的算法。

“笨!这棵树难道就白构建了!”小Hi教训完小Ho,继续道:“看好了!”

提示二:如何使用Trie树

提示三:在建立Trie树时同时进行统计!

“那么现在!赶紧去用代码实现吧!”小Hi如是说道

输入

输入的第一行为一个正整数n,表示词典的大小,其后n行,每一行一个单词(不保证是英文单词,也有可能是火星文单词哦),单词由不超过10个的小写英文字母组成,可能存在相同的单词,此时应将其视作不同的单词。接下来的一行为一个正整数m,表示小Hi询问的次数,其后m行,每一行一个字符串,该字符串由不超过10个的小写英文字母组成,表示小Hi的一个询问。

在20%的数据中n, m<=10,词典的字母表大小<=2.

在60%的数据中n, m<=1000,词典的字母表大小<=5.

在100%的数据中n, m<=100000,词典的字母表大小<=26.

本题按通过的数据量排名哦~

输出

对于小Hi的每一个询问,输出一个整数Ans,表示词典中以小Hi给出的字符串为前缀的单词的个数。

样例输入
5
babaab
babbbaaaa
abba
aaaaabaa
babaababb
5
babb
baabaaa
bab
bb
bbabbaab
样例输出
1
0
3
0
0



import java.util.Scanner;


class TrieNode{
	private static final int MAXL = 26;
	TrieNode[] child;
	int count;
	char value;	
	public TrieNode(){
		child = new TrieNode[MAXL];
		count = 1; 
	}
}


class TrieTree{
	public void createTree(TrieNode node,String str){
		if(str==null||str.length()==0){
			return;
		}
		char[] chs = str.toCharArray();
		int len = str.length();
		for(int i=0;i<len;i++){
			int pos = chs[i] -'a';
			if(node.child[pos]==null){
				node.child[pos] = new TrieNode();
			}else{
				node.child[pos].count++;
			}
			node.child[pos].value = chs[i];
			node = node.child[pos];
		}
	}
	
	public int query(TrieNode node,String str){
		if(str==null||str.length()==0){
			return -1;
		}
		char[] chs = str.toCharArray();
		int len = str.length();
		for(int i=0;i<len;i++){
			int pos = chs[i] - 'a';
			if(node.child[pos]==null){
				return 0;
			}else{
				node = node.child[pos];
			}
		}
		return node.count;
	}
}
public class Main {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scan = new Scanner(System.in);
		TrieTree tree = new TrieTree();
		TrieNode root = new TrieNode();
		int T = scan.nextInt();
		String str = "";
		while(T--!=0){
			str = scan.next();
			tree.createTree(root, str);
		}
		T = scan.nextInt();
		while(T--!=0){
			str = scan.next();
			int num = tree.query(root, str);
			System.out.println(num);
		}
	}
}


#define _CRT_SECURE_NO_WARNINGS #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; int trie[700][26],fail[700],state[700],n; int vis[700][1 << 12],cnt=0,fa[700],ch[700]; void insert(char* s,int x) { int n = strlen(s); int now=0; for (int i = 0; i < n; i++) { int bit = s[i] - &#39;a&#39;; if (trie[now][bit] == 0)trie[now][bit] = ++cnt; now = trie[now][bit]; } state[now] |= 1 << x; } void buildfail() { queue<int>line; for(int i=0;i<26;i++) if (trie[0][i]) { fail[trie[0][i]] = 0; line.push(trie[0][i]); } while (!line.empty()) { int now = line.front(); line.pop(); for (int i = 0; i < 26; i++) { if (trie[now][i]) { fail[trie[now][i]] = trie[fail[now]][i]; state[trie[now][i]] = state[trie[now][i]] | state[trie[fail[now]][i]]; line.push(trie[now][i]); } else trie[now][i] = trie[fail[now]][i]; } } } void print(int ed) { int num[700],ans=0; while (ed) { num[ans++] = ch[ed]; ed = fa[ed]; } for (int i = 0; i < ans; i++) printf("%c", num[i] + &#39;a&#39;); } void solve() { queue<pair<int, int>>line; line.emplace(0, 0); vis[0][0] = 1; while (line.size()) { auto [now, st] = line.front(); line.pop(); if (st == ((1 << n) - 1)) { print(now); return; } for (int i = 0; i < 26; i++) { int v = trie[now][i]; int newst = st | state[v]; if (!vis[v][newst]) { line.emplace(v, newst); vis[v][newst] = 1; fa[v] = now; ch[v] = i; } } } } int main() { scanf("%d", &n); for (int i = 0; i < n; i++) { char a[51]; scanf("%s", a); insert(a,i); } buildfail(); solve(); }哪里有问题
最新发布
03-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值