Trie 字典树

支持查询多个字符串的最长公共前缀,每个前缀的出现的次数,不同字符串的个数等等。


建树:

inline void built(char *s,ll root) {
	for (ll i=1;i<=strlen(s+1);++i) {
		ll lett=s[i]-'a'+1;
		if (!trie[root][lett]) trie[root][lett]=++tot;
		root=trie[root][lett];
                sum[root]++//这里代表以这个字符为结尾的前缀出现次数
	}
	correct[root]=1;//这里代表当前字符串结尾位置
    
}
for (ll i=1;i<=n;++i) {
		scanf("%s",s+1);
		built(s,0);
}

查询

inline ll find(char *s,ll root) {
	for (ll i=1;i<=strlen(s+1);++i) {
		ll lett=s[i]-'a'+1;
		if (!trie[root][lett]) return 0;
		root=trie[root][lett];
	}
    
   //——————————以上部分为遍历字典树——————————————
	if (!correct[root]) return 0;
	if (!sum[root]) {
		sum[root]++;
		return 1;
	}
	else return 2;
} 

模板题:于是他错误的点名开始了


典例题型:

  • 字典树+dp

Remember the Word

倒叙枚举每一个后缀,用每个后缀来遍历字典树并进行转移

  • 字典树+拓扑判环

[USACO12DEC]First! G

首先,若某字符串是另一个字符串的前缀,一定不可行。所以我们先建树,然后用每一个字符串在树上遍历,发现某一个字符串的结尾标记就立刻判定不可行。接下来,若想让这个字符串的字典序靠前,那么这个字符串内的每个字母都要优先于同层其他字母,所以可以建有向无环图来判环——将当前枚举到的字符串的每个字符都向同层其他字符连有向边,最后拓扑判环,若有环则一定不可行。

  • 字典树上dfs

[JSOI2009] 电子字典

inline void dfs(ll root,ll l,ll f) {
	if (l==len&&ed[root]&&!f) {
		flag=1;
		return;
	}
	if (l==len&&ed[root]&&f) {
		if (!vis[root]) vis[visx[++vtot]=root]=1;
		return;
	}
	if (!f) {
		if (l<len) dfs(root,l+1,1);
		for (ll i=0;i<26;++i) {
			if (!trie[root][i]) continue;
			if (g[l]-'a'!=i) dfs(trie[root][i],l+1,1);
			dfs(trie[root][i],l,1);
		}
	}
	if (l>=len) return;
	if (trie[root][g[l]-'a']) dfs(trie[root][g[l]-'a'],l+1,f);
	
}  
posted @ 2023-06-20 16:49  Pwtking  阅读(18)  评论(0)    收藏  举报