一道机试题:写一个字典实现以下功能:
(1)插入某个字符串
(2)删除某个字符串为前缀的所有字符串
(3)搜索某个字符串为前缀的字符串,找到输出YES,否则输出NO
看到这个是有想到索引,但是这个前缀不太好实现,于是上网看有没有什么好的实现方式。又认识到了一种新的字典的实现方式:字典树。这个结构真的太适合有前缀的字符串存储了!!
字典树参见博客:https://blog.csdn.net/weixin_39778570/article/details/81990417
我在作者的基础上,改写了search函数,可以查找前缀为指定字符串的字符串。又编写了删除函数,可以删除前缀为某一特定字符串的字符串。代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX_NODE = 1000000 + 10;
const int CHARSET = 26;
int trie[MAX_NODE][CHARSET] = {0};
int color[MAX_NODE] = {0};
int k = 1;
void insert(char *w){
int len = strlen(w);
int p = 0;
for(int i=0; i<len; i++){
int c = w[i] - 'a';
if(!trie[p][c]){
trie[p][c] = k;
k++;
}
p = trie[p][c];
}
color[p] = 1;
}
int search(char *s){
int len = strlen(s);
int p = 0;
for(int i=0; i<len; i++){
int c = s[i] - 'a';
if(!trie[p][c]) return 0;
p = trie[p][c];
}
return 1;
}
int dele(char *s){
int len = strlen(s);
int p = 0;
for (int i = 0; i < len; ++i) {
int c = s[i] - 'a';
if(!trie[p][c]) return 0;
if(i != len-1)
p = trie[p][c];
else
trie[p][c] = 0;
}
return 1;
}
int main(){
bool flag = true;
while (flag){
printf("choose:1:insert\n2:delete\n3search\n4:end\n");
int order;
scanf("%d", &order);
switch (order){
case 1:{
printf("insert num:\n");
int num;
scanf("%d", &num);
char s[20];
while(num--){
scanf("%s", s);
insert(s);
}
}
case 2:{
printf("delete num:\n");
int num;
scanf("%d", &num);
char s[20];
while(num--){
scanf("%s", s);
if(dele(s)) printf("delete successfully!\n");
else printf("delete failed!\n");
}
}
case 3:{
printf("search num:\n");
int num;
scanf("%d", &num);
char s[20];
while(num--){
scanf("%s", s);
if(search(s)) printf("YES\n");
else printf("NO\n");
}
}
case 4: flag = false;
}
}
return 0;
}