KMP算法(未优化版本,算法导论原版)
2017-12-12 20:42
288 查看
kmp是经典的单模式串字符串匹配算法,对于一个字符串在长文本中的匹配很有效。 kmp算法包括两部分,对模式串的预处理和模式串匹配**
1、模式串预处理
这一部分关键在于next数组的构造,相当于对模式串进行kmp匹配。注意,字符串数组与next数组的首字符不存储信息。
next数组中储存当该字符的下一个不匹配时,下一步应当跳转到哪里,即,到此为止该字符串的最长公共前缀,后缀的长度。
详细见代码注释
void next(int *next, char *c)//字符串从c[1]开始赋值 { //k为要比较的字符的前一个的下标,一开始比较c[1]c[2],所以k初始化为0 int k = 0; //首字符的next值初始化为0,说明包①含这个字符的字符串前后缀长为0,②即要比较的字符c[1]的前一个 next[1] = 0;//注意next数组值的两层含义 //一开始比较c[1]c[2],i初始化为2, for (int i = 2; i < strlen(c); i++)//next数组最后一个的值比strlen值小一,所以不要取等 { //当k可以回溯且不匹配时,让k回溯 //k初始化为0,保证可回溯,即k>0 while (k > 0 && c[i] != c[k + 1]) { k = next[k];//对前串来说a[k]是a1中前缀的最后一个字符所在位置 } if (c[i] == c[k + 1])//若匹配则k+1, k++; next[i] = k;//包含i的字符串的前缀长=加过1的k。 } }
2、kmp匹配部分
原理与模式串匹配相似,只不过是两个字符串的匹配
void kmp(char *t, char *p)//t为长串,p为短串 { int *next; next = (int *)malloc(sizeof(int)*(strlen(p)+1)); buildnext(next, p); int k = 0;//k为要比较的字符的前一个的下标,一开始比较模式串中的c[1],k初始化为0 for (int i = 1; i < strlen(t); i++)//长串的最后一个字符的下标为长度-1 { while (k>1 && p[k + 1] != t[i]) k = next[k]; if (p[k + 1] == t[i]) k++; if (k == strlen(p)-1) { printf("开始下标为%d\n", i - strlen(p)+1+1); k = next[k];//寻找下一个匹配串 } }
这种原始的kmp算法有一个弊端,当字符串重复性很高时(例如ababababag),它的效率和朴素匹配没啥区别了。因为当重复性很高时,如果有一位失配,那么再向后移动仍然失配。
相关文章推荐
- Dijkstra 之最短路径算法(无优化版本) By ACReaper
- C++:罗列出1~100000000的所有雷劈数(算法优化版本)
- 算法导论第32章——字符串匹配问题(KMP算法)
- [时空权衡]字符串匹配KMP算法代码(引自算法导论)
- 字符串匹配算法——Sunday算法和KMP算法(java版本)
- KMP算法之最终实现及优化 - 数据结构和算法39
- KMP算法总结(纯算法,为优化,没有学应用)
- KMP算法代码实现和优化(不太能理解具体的过程和该算法思想)
- KMP算法及其优化算法
- 算法导论:快速排序优化算法!
- 算法导论7.3快速排序的随机化版本
- 算法导论——快排序算法及优化
- Dijkstra算法之优先队列优化版本 By ACReaper Dijkstra
- 【算法导论-006】冒泡排序及其优化(BubbleSort)
- 算法导论—快排及优化以及和STL sort 的比较
- 经典算法之KMP算法及其优化
- Hopcroft-Karp算法模板(匈牙利算法的优化版本)
- 根据算法思路自己实现了kmp算法(未优化)
- 快速排序(算法导论中的版本)
- 重复字符串的判定问题(kmp 算法之优化版本)