字典树

开始学习字典树,记录一下。

字典树的巧妙就在于把所有的单词都放在了一棵树中,那么当你查询的时候,你只要查询这棵树就行,而不是遍历每个单词。

学习网站

查询输入的单词中是否出现了该前缀。

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
#include <bits/stdc++.h>
using namespace std;
//查询一些单词中某个前缀是否出现过
int tree[10005][26]; //第一维大小应该是所有字母的总长度
int tot = 1;
int insert(string s)
{
int rt = 1;
for(int i = 0; i < s.size(); ++i)
{
int x = s[i] - 'a';
if(!tree[rt][x])
{
tree[rt][x] = ++tot;
}
rt = tree[rt][x];
}
return 1;
}

int find(string s) //查询是否出现过这个前缀
{
int rt = 1;
for(int i = 0; i < s.size(); ++i)
{
int x = s[i] - 'a';
if(!tree[rt][x]) return 0;
rt = tree[rt][x];
}
return 1;
}
int main()
{
int n, m;
cin >> n >> m;
string s;
for(int i = 1; i <= n; ++i)
{
cin >> s;
insert(s);
}
for(int i = 1; i <= m; ++i)
{
cin >> s;
if(find(s))
cout << "have found" << '\n';
else
cout << "not found" << '\n';
}
}

查询一些单词中是否出现了某个单词。

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
#include <bits/stdc++.h>
using namespace std;
//查询一些单词中某个单词是否出现过
int tree[10005][26];
int tot = 1;
bool is[10005];
int insert(string s)
{
int rt = 1;
for(int i = 0; i < s.size(); ++i)
{
int x = s[i] - 'a';
if(!tree[rt][x])
{
tree[rt][x] = ++tot;
}
rt = tree[rt][x];
}
is[rt] = 1;
}

int find(string s) //查询是否出现过这个单词
{
int rt = 1;
for(int i = 0; i < s.size(); ++i)
{
int x = s[i] - 'a';
if(!tree[rt][x]) return 0;
rt = tree[rt][x];
}
return is[rt];
}
int main()
{
int n, m;
cin >> n >> m;
string s;
for(int i = 1; i <= n; ++i)
{
cin >> s;
insert(s);
}
for(int i = 1; i <= m; ++i)
{
cin >> s;
if(find(s))
cout << "have found" << '\n';
else
cout << "not found" << '\n';
}
}

查询在某些单词中一个单词的出现次数

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
#include <bits/stdc++.h>
using namespace std;
//查询一些单词中某个单词的出现次数
int tree[10005][26];
int tot = 1;
bool is[10005];
int sum[10005];
int insert(string s)
{
int rt = 1;
for(int i = 0; i < s.size(); ++i)
{
int x = s[i] - 'a';
if(!tree[rt][x])
{
tree[rt][x] = ++tot;
}
sum[tree[rt][x]]++;
rt = tree[rt][x];
}
is[rt] = 1;
}

int find(string s) //查询出现这个单词的次数
{
int rt = 1;
for(int i = 0; i < s.size(); ++i)
{
int x = s[i] - 'a';
if(!tree[rt][x]) return 0;
rt = tree[rt][x];
}
return sum[rt];
}
int main()
{
int n, m;
cin >> n >> m;
string s;
for(int i = 1; i <= n; ++i)
{
cin >> s;
insert(s);
}
for(int i = 1; i <= m; ++i)
{
cin >> s;
cout << find(s) << '\n';
}
}

其实这三种代码都是稍微改动了一下,重要的是理解trie树的构建。