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

浙公网安备 33010602011771号