题目描述
维护一个字符串集合,支持两种操作:
“I x”向集合中插入一个字符串x;
“Q x”询问一个字符串在集合中出现了多少次。
共有N个操作,输入的字符串总长度不超过 105,字符串仅包含小写英文字母。
输入格式
第一行包含整数N,表示操作数。
接下来N行,每行包含一个操作指令,指令为”I x”或”Q x”中的一种。
输出格式
对于每个询问指令”Q x”,都要输出一个整数作为结果,表示x在集合中出现的次数。
每个结果占一行。
数据范围
1≤N≤2∗104
输入样例:
5
I abc
Q abc
Q ab
I ab
Q ab
输出样例:
1
0
1
算法1
根据trie树的意义 自己设计了一个结构体
每个节点额外增加一个当前字母是不是某一个字符串的结尾 另外根据本题题意又增加了一个元素,记录到此节点的字符串被insert了几次(也就是本体的答案)
C++ 代码
#include <iostream>
#include <vector>
#include <string>
using namespace std;
/*
5
I abc
Q abc
Q ab
I ab
Q ab
*/
/*
1
0
1
*/
struct Node {
vector<struct Node*> next;
int isEnd;
int count;
Node() {
next = vector<struct Node*>(26, NULL);
isEnd = 0;
count = 0;
}
};
struct Node root;
void Insert(string& s)
{
struct Node* p = &root;
for (int i = 0; i < s.size(); i++) {
char c = s[i];
int idx = c - 'a';
if (p->next[idx] == NULL) {
struct Node* pp = new Node();
pp->count++;
p->next[idx] = pp;
p = pp;
}
else {
p = p->next[idx];
p->count++;
}
}
p->isEnd = 1;
}
void Query(string& s)
{
struct Node* p = &root;
for (int i = 0; i < s.size(); i++) {
char c = s[i]; int idx = c - 'a';
if (p->next[idx] == NULL) {
cout << 0 << endl; return;
}
else {
p = p->next[idx];
}
}
if (p->isEnd == 1)
cout << p->count << endl;
return;
}
int main()
{
int n;
cin >> n;
while (n--) {
string s;
char QI;
cin >> QI >> s;
if (QI == 'I') {
Insert(s);
}
else {
Query(s);
}
}
return 0;
}
然而 由于用了vector 而且使用了临时分配内存 这速度是相当的慢 还不如用哈希