KMP模式匹配算法的一些理解
2012-03-28 01:05
387 查看
先上代码:
KMP算法的精髓在于:建立匹配串的模式数组(Next[])
1. 什么是Next数组?
传统的字符串匹配采用的是最简单最二逼的迭代,这必然会造成大量不必要的操作,Next数组的存在就是为了去除这些不必要的操作。
每一个Next数组的下标都映射了一个匹配串(AnalyzeThis)中具有相同下标的元素,当这个元素与主串(Text)的某个元素(设为a)不匹配的时候,
Next立功的时候就到了:
它会告诉这个傻逼的电脑,应该继续从匹配串(AnalyzeThis)的哪个元素开始继续与a进行匹配工作。
2. Next数组的建立原理与数值意义
如前文所述,Next充当的是一个指挥着的角色。
这个是Next数组的定义:
(这是第一个元素) ||======================||=(这货就是传说中的第K个元素)===============....(1)
===============================||========================|| =(这个是第J个元素)============....(2)
如上面图所示,这两行表示的是同一串字符,为编译理解我将它表述为两行。其中第一行红色部分指代字符串P1 ...Pk-1
,第二行红色部分指代字符串Pj-k+1......Pj-1, 他俩相等。
相信看到这里大家都清楚了。因为Next[J]被使用的前提是,匹配串(Key)的J元素的前面所有元素都与主串某区域匹配,但主串的a元素与匹配串中K元素不匹配。
即等价于(2)的红色部分(字符串Pj-k+1......Pj-1)与主串相同区域匹配,即等价于(1)中的红色部分(字符串P1 ...Pk-1)
与主串的相同区域匹配,又因为这是一个最大的字串(参照上面的MAX定义),所以我只要继续比较匹配串中的K元素与主串中的a元素即可。
Next[J] = K 的原理如上所示~
再来看实现的代码:
这货的主要思想是,1. 将 AnalyzeThis[preChar] == AnalyzeThis[posChar] 的关系表达在第 posChar + 1个元素上,而这种关系又与 posChar + 1上的元素无关!这是一个不断重复的过程..2. 通过 preChar = Next[preChar] 回溯,找到先前一个较短的串,再进行比较..
PS: KMP已经OUT了,但这种算法设计思路相当经典..
#include <string> using namespace std; /****************************KMP模式匹配算法****************************/ void setIndexOfNext(const string &AnalyzeThis, int *Next){//AnalyzeThis, Next从0开始存储有效数据.. const int Num = AnalyzeThis.size() - 1; int preChar = -1, posChar = 0; Next[0] = -1; while(posChar < Num){ if(preChar == -1 || AnalyzeThis[preChar] == AnalyzeThis[posChar]){ ++preChar; ++posChar; Next[posChar] = preChar; } else preChar = Next[preChar]; } } int First_Index_of(const string &Text, const string &Key, int i){//i用来定位Text的字符 int Next[300]; int temIndexOfKey = 0; setIndexOfNext(Key, Next); const int Num_Text = Text.size(); const int Num_Key = Key.size(); while(i < Num_Text && temIndexOfKey < Num_Key){ if(temIndexOfKey == -1 || Text[i] == Key[temIndexOfKey]){ ++i; ++temIndexOfKey; } else temIndexOfKey = Next[temIndexOfKey]; } if(temIndexOfKey == Key.size())//结束时i指向符合单词的最后一个字母所在的下标的后一位 return i - Key.size(); else return -1; } /****************************KMP模式匹配算法优化版****************************/ void better_setIndexOfNext(const string &AnalyzeThis, int *Next){//AnalyzeThis, Next从0开始存储有效数据.. const int Num = AnalyzeThis.size() - 1; int preChar = -1, posChar = 0; Next[0] = -1; while(posChar < Num){ if(preChar == -1 || AnalyzeThis[preChar] == AnalyzeThis[posChar]){ ++preChar; ++posChar; if(AnalyzeThis[preChar] != AnalyzeThis[posChar]) Next[posChar] = preChar; else Next[posChar] = Next[preChar];//再次去掉多余的比较.. } else preChar = Next[preChar]; } } int better_First_Index_of(const string &Text, const string &Key, int i){//i用来定位Text的字符 int Next[300]; int temIndexOfKey = 0; better_setIndexOfNext(Key, Next); const int Num_Text = Text.size(); const int Num_Key = Key.size(); while(i < Num_Text && temIndexOfKey < Num_Key){ if(temIndexOfKey == -1 || Text[i] == Key[temIndexOfKey]){ ++i; ++temIndexOfKey; } else temIndexOfKey = Next[temIndexOfKey]; } if(temIndexOfKey == Key.size())//结束时i指向符合单词的最后一个字母所在的下标的后一位 return i - Key.size(); else return -1; }
KMP算法的精髓在于:建立匹配串的模式数组(Next[])
1. 什么是Next数组?
传统的字符串匹配采用的是最简单最二逼的迭代,这必然会造成大量不必要的操作,Next数组的存在就是为了去除这些不必要的操作。
每一个Next数组的下标都映射了一个匹配串(AnalyzeThis)中具有相同下标的元素,当这个元素与主串(Text)的某个元素(设为a)不匹配的时候,
Next立功的时候就到了:
它会告诉这个傻逼的电脑,应该继续从匹配串(AnalyzeThis)的哪个元素开始继续与a进行匹配工作。
2. Next数组的建立原理与数值意义
如前文所述,Next充当的是一个指挥着的角色。
这个是Next数组的定义:
(这是第一个元素) ||======================||=(这货就是传说中的第K个元素)===============....(1)
===============================||========================|| =(这个是第J个元素)============....(2)
如上面图所示,这两行表示的是同一串字符,为编译理解我将它表述为两行。其中第一行红色部分指代字符串P1 ...Pk-1
,第二行红色部分指代字符串Pj-k+1......Pj-1, 他俩相等。
相信看到这里大家都清楚了。因为Next[J]被使用的前提是,匹配串(Key)的J元素的前面所有元素都与主串某区域匹配,但主串的a元素与匹配串中K元素不匹配。
即等价于(2)的红色部分(字符串Pj-k+1......Pj-1)与主串相同区域匹配,即等价于(1)中的红色部分(字符串P1 ...Pk-1)
与主串的相同区域匹配,又因为这是一个最大的字串(参照上面的MAX定义),所以我只要继续比较匹配串中的K元素与主串中的a元素即可。
Next[J] = K 的原理如上所示~
再来看实现的代码:
while(posChar < Num){ if(preChar == -1 || AnalyzeThis[preChar] == AnalyzeThis[posChar]){ ++preChar; ++posChar; Next[posChar] = preChar; } else preChar = Next[preChar]; }
这货的主要思想是,1. 将 AnalyzeThis[preChar] == AnalyzeThis[posChar] 的关系表达在第 posChar + 1个元素上,而这种关系又与 posChar + 1上的元素无关!这是一个不断重复的过程..2. 通过 preChar = Next[preChar] 回溯,找到先前一个较短的串,再进行比较..
PS: KMP已经OUT了,但这种算法设计思路相当经典..
相关文章推荐
- 关于KMP模式匹配算法的个人理解
- 自我理解的KMP 算法 模式匹配
- 理解与实现KMP模式匹配算法
- KMP模式匹配算法详解(耐心看完定会理解)
- 快速模式匹配算法(KMP)的深入理解
- 彻头彻尾地理解KMP字符串模式匹配算法
- KMP模式匹配算法的两点理解
- 教材上关于模式匹配中的求next数组的算法不易理解,本人自己编写了一个具有相同功能的子函数
- 模式匹配算法KMP
- kmp模式匹配算法
- 串的模式匹配算法---KMP
- KMP模式匹配算法总结
- KMP模式匹配算法C++实现
- 关于KMP模式匹配的理解
- 数据结构之串的模式匹配算法(KMP)
- KMP模式匹配算法-----ACM程序设计…
- KMP模式匹配算法
- 串-KMP模式匹配算法
- 模式匹配的KMP 算法
- KMP模式匹配算法