Knuth-Morris-Pratt字符串搜索算法:不含DFA的版本

2021-01-22 19:04:56

由KMP算法生成的DFA稀疏且具有我们可以轻松观察到的规律性。一种流行的优化方法不是使用DFA,而是使用较小的"部分匹配"。表:

// Knuth–Morris–Pratt算法//复制自http://cprogramming.com/snippets/source-code/knuthmorrispratt-kmp-string-search-algorithmchar * kmp_search(char * haystack,size_t haystack_size,char * needle,size_t needle_size){int * T; int i,j; char *结果= NULL;如果(needle_size == 0)返回干草堆; / *构造查找表* / T =(int *)malloc((needle_size + 1)* sizeof(int)); T [0] = -1;对于(i = 0; i< needle_size; i ++){T [i + 1] = T [i] + 1;而(T [i + 1]≥0&针[i]!=针[T [i + 1] -1])T [i + 1] = T [T [i + 1] -1 ] + 1; } printf("重新启动表:\ n");对于(i = 0; i< needle_size + 1; i ++)printf(" T [%d] =%d \ n&#34 ;, i,T [i]); / *对(i = j = 0; i = 0)print_compare(干草堆,i,针,j); if(j< 0 || haystack [i] == needle [j]){++ i,++ j;如果(j == needle_size){结果=干草堆+ i-j;打破; }} else {j = T [j]; if(j ==-1)printf("从头开始重新起针\ n");否则print_state_needle(needle,j); }; } free(T);返回结果;}

重新启动表:T [0] =-1T [1] = 0T [2] = 1T [3] = 0要进行比较:eex鳗鱼^要进行比较:eex鳗鱼^要进行比较:eex鳗鱼^重新启动针at:鳗鱼^要比较:eex鳗鱼鳗鱼^重新启动针在:eel ^要比较:eex鳗鱼鳗鱼^重新开始的针头要进行比较:eex eel eel ^^重新开始的针头要进行比较:eex鳗鱼鳗鱼^要比较:鳗鱼鳗鱼^要比较:鳗鱼鳗鱼^

T []表很小,适合用于高速缓存。但是请注意:一个字符在重新启动的情况下将被加载两次。但这很好,此时它仍然被高速缓存。

现在有趣的事情是:如果'部分匹配'表是空的(全零),搜索功能可以天真地实现,就像我在第一部分中尝试过的那样。

这些是诸如' tesa',' lee','香蕉'的单词的情况。但是,必须为'这样的单词构造一个非空表。 eel',oops',' test',' elee' -这些单词在单词中重复了前缀(最少1个字符),但这对于' banana'而言并非如此。 -没有重复的前缀。