找出文本中存在的坏单词-后缀trie

来源:互联网 发布:vscode mactype 编辑:程序博客网 时间:2024/05/08 16:13

假设给定一个关键词rob,如果某一个单词中包含此字符串,那么就断定此字符串为bad word。如problem就包含rob,那么它就是bad word。其实这种叙述是:“判断一个字符串是否是另一个字符串的子串”的另外一种描述。熟悉字符串匹配的人都知道,这个问题可以用KMP算法很快就能够解决。但是就像我们不嫌弃自己的钱多的一样,方法多了,路子就多了。所以决定应用后缀trie来解决这个问题。后缀trie是trie树的一种变种形式。给定字符串S=s1s2s3s4....sn,把si...sn称作S的一个后缀,其中 1<=i<=n,按照次序,我们把S的每一个后缀都插入到一个trie树中,最终形成的树,就叫S的后缀trie树。对于单词problem的后缀依次为:

problem, roblem, oblem, blem, lem, em , m.给出这个单词的后缀trie:


建立好了后缀trie便可以清楚的看到,在树中寻找rob是相当容易的事情,只需要3次比对,也就是length of “rob”的长度。可以说是如果trie建立好以后,寻找什么都是很快的。但是在建立后缀trie的时候却要耗费很大的空间和很长的时间,这就是为什么后缀trie没有被人们所亲睐的原因。仔细看图,体会一下它的奇妙之处吧,它涵盖了problem中以任何字母开头,在一定长度内的任何子串。下面给出代码,它的时间和空间复杂度都在O(n^2).

#include<stdio.h>#include<stdlib.h>#include<string.h>#define CHILD_NUM 26typedef struct trie_node{char key;struct trie_node *child[CHILD_NUM];}TrieNode, *TrieTree;TrieNode *create_node(char key) {TrieNode *temp = (TrieNode*)malloc(sizeof(TrieNode));temp->key = key;for(int i = 0; i < CHILD_NUM; i++) {temp->child[i] = NULL;}return temp;}void insert_trie(TrieTree T, char *p_word) {TrieNode *p = T;while(*p_word) {if(p->child[*p_word - 'a'] == NULL) {p->child[*p_word - 'a'] = create_node(*p_word);}p = p->child[*p_word - 'a'];p_word++;}}int search_trie(TrieTree T, char *p_word) {TrieNode *p = T;while(p && *p_word) {if(p->child[*p_word - 'a'] == NULL) {return 0;} else {p = p->child[*p_word - 'a'];p_word++;}}if(p == NULL && *p_word != '\0') {return 0;} else {return 1;}}void main() {TrieTree T = create_node(' ');char word[] = "problem";char *p = word;char bad_word[] = "rob";int len = strlen(word);int i;for(i = 0; i < len; i++) {insert_trie(T, p + i);}if(search_trie(T, bad_word)) {printf("this word is bad word!\n");} else {printf("this word is good word!\n");}}


原创粉丝点击