字典树 用于统计,排序和保存大量的字符串(但不仅限于字符串,如01字典树)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 const int N = 1000050 ;int trie[N][26 ];int cnt[N];int id;void insert (string s) { int p = 0 ; for (int i = 0 ; i < s.size(); i++) { int x = s[i] - 'a' ; if (trie[p][x] == 0 ) trie[p][x] = ++id; p = trie[p][x]; } cnt[p]++; } int find (string s) { int p = 0 ; for (int i = 0 ; i < s.size(); i++) { int x = s[i] - 'a' ; if (trie[p][x] == 0 )return 0 ; p = trie[p][x]; } return cnt[p]; }
检索字符串 如果是查询某个单词 的话,我们用bool变量 v[i]表示节点i是否是单词结束的标志。 那么最后return的是v[root],所以在插入操作中插入完每个单词是,要对单词最后一个字母的v[i]置为true,其他的都是false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define maxn 2000010 using namespace std ; int tot=1 ,n;int trie[maxn][26 ];void insert (char *s,int rt) { for (int i=0 ;s[i];i++) { int x=s[i]-'a' ; if (trie[rt][x]==0 ) { trie[rt][x]=++tot; } rt=trie[rt][x]; } } bool find (char *s,int rt) { for (int i=0 ;s[i];i++) { int x=s[i]-'a' ; if (trie[rt][x]==0 )return false ; rt=trie[rt][x]; } return true ; } char s[22 ];int main () { tot=0 ; int rt=1 ; scanf ("%d" ,&n); for (int i=1 ;i<=n;i++) { cin >>s; insert(s,rt); } scanf ("%d" ,&n); for (int i=1 ;i<=n;i++) { cin >>s; if (find(s,rt))printf ("YES\n" ); else printf ("NO\n" ); } return 0 ; }
查询前缀出现的次 数 开一个sum[],表示位置i被访问过的次数,那么最后return的是sum[root],插入操作中每访问一个节点,都要让他的sum++,这里前缀的次数是标记在前缀的最后一个字母所在位置的后一个位置上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std ; int trie[400001 ][26 ],len,root,tot,sum[400001 ];bool p;int n,m; char s[11 ];void insert () { len=strlen (s); root=0 ; for (int i=0 ;i<len;i++) { int id=s[i]-'a' ; if (!trie[root][id]) trie[root][id]=++tot; sum[trie[root][id]]++; root=trie[root][id]; } } int search () { root=0 ; len=strlen (s); for (int i=0 ;i<len;i++) { int id=s[i]-'a' ; if (!trie[root][id]) return 0 ; root=trie[root][id]; } return sum[root]; } int main () { scanf ("%d" ,&n); for (int i=1 ;i<=n;i++) { cin >>s; insert(); } scanf ("%d" ,&m); for (int i=1 ;i<=m;i++) { cin >>s; printf ("%d\n" ,search()); } }
维护异或极值 将数的二进制表示看做一个字符串,就可以建出字符集为 {0,1} 的 trie 树。