题目
维护一个字符串集合,支持两种操作:
I x
向集合中插入一个字符串 ;Q x
询问一个字符串在集合中出现了多少次。
共有 个操作,输入的字符串总长度不超过 ,字符串仅包含小写英文字母。
输入格式
第一行包含整数 ,表示操作数。
接下来 行,每行包含一个操作指令,指令为 I x
或 Q x
中的一种。
输出格式
对于每个询问指令 Q x
,都要输出一个整数作为结果,表示 在集合中出现的次数。
每个结果占一行。
数据范围
输入样例:
5
I abc
Q abc
Q ab
I ab
Q ab
输出样例:
1
0
1
解题
方法一:Trie 树
思路
Trie树模版:Trie 树
Trie 树
Trie 树是一种用于高效地存储和查找字符串集合的数据结构。
我们可以用数组来模拟树状结构:sons[][]
中存的是每个节点的子节点在 sons
中的下标,cnts
中存的是某个节点为结尾的数量,下标是 的点既表示根节点又表示空节点,idx
与数组模拟单链表中的 idx
相同也表示当前用到了哪个节点。
- 插入操作:遍历字符串,维护一个指针(
p
)从根节点开始,如果子节点中不存在当前字符就创建一个新的节点,然后走到下一个节点,遍历完成后p
会指向最后一个字符所在节点,把这个节点上的计数增加表示以该节点结尾的字符串数量增加。 - 查询操作:遍历字符串,维护一个指针(
p
)从根节点开始,如果子节点中不存在当前字符说明树中不存在该字符串,直接返回0
,否则继续走到下一个节点,遍历完成后p
会指向最后一个字符所在节点,返回该节点的数量(cnts[p]
)即可。
代码
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int sons[N][26], cnts[N], idx;
int n;
void insert(char word[]) {
int p = 0;
for (int i = 0; word[i]; ++i) {
int curr = word[i] - 'a';
if (!sons[p][curr]) sons[p][curr] = ++idx;
p = sons[p][curr];
}
++cnts[p];
}
int count(char word[]) {
int p = 0;
for (int i = 0; word[i]; ++i) {
int curr = word[i] - 'a';
if (!sons[p][curr]) return 0;
p = sons[p][curr];
}
return cnts[p];
}
int main() {
scanf("%d\n", &n);
while (n--) {
char ope, s[N];
scanf("%c %s\n", &ope, s);
if (ope == 'I') insert(s);
else printf("%d\n", count(s));
}
return 0;
}
import java.util.*;
import java.io.*;
public class Main {
static final int N = (int) 1e5 + 10;
static int[][] sons = new int[N][26];
static int[] cnts = new int[N];
static int idx = 0;
static void insert(String word) {
int n = 0;
for (char ch : word.toCharArray()) {
int curr = ch - 'a';
if (sons[n][curr] == 0) sons[n][curr] = ++idx;
n = sons[n][curr];
}
++cnts[n];
}
static int count(String word) {
int n = 0;
for (char ch : word.toCharArray()) {
int curr = ch - 'a';
if (sons[n][curr] == 0) return 0;
n = sons[n][curr];
}
return cnts[n];
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(in.readLine());
while (n-- > 0) {
String line = in.readLine();
if (line.charAt(0) == 'I') insert(line.substring(2));
else System.out.println(count(line.substring(2)));
}
}
}
评论区