KMP 字符串的匹配算法
来源:互联网 发布:h3c端口聚合配置验证 编辑:程序博客网 时间:2024/06/05 22:37
一、KMP算法与Brute-force算法的最大区别就在于KMP算法在比较时,主串的指针i不用回溯,只需回溯字串的指针j
而Brute-force算法就是简单的从第一个字符比到最后一位,这时需要对主串的i进行回溯,这样算法的比较次数明显增多
KMP的算法复杂度可为O(m +n)而Brute-force的算法复杂度可为O(m*n)。
二、在做KMP时我们可以知道每一次字串j的回溯,即每一次字串后移的位数等于匹配的位数减去部分匹配的位数
即可以得到一公式 移位数 = 匹配位数 - 部分匹配位数
如何得到部分匹配位数呢?
这是由字串的前缀与后缀的最大共同的字符串决定的。如ABDAB这是部分匹配位数为2
三、如何推算next[]呢?
由特殊到一般:
假设:有next[j]= k,即“t[0]...............t[k-1]”=''t[j-k]................t[j-1]'',0<k<j,此时next[j+1]有两种情况
字串:
t = t[0].........t[j-k]......t[j-1].......t[j]......t[m-1]
t' = t[0].......t[k-1] t[k]
t' =t[0]....................t[k']
if(t[k] == t[j]) { next[j+1] = next[j] +1 = next[k] +1;}//此时我们就需从字串t'中找到t' 等于t[k]的情况else if(t[k ] != t[j]){ next[j+1] = k'+1= next[k]+1;}//如果没找到则k = 0else{ next[j+1] = 0;}
//以上代码只是分析使用的是伪码。
KMP代码:
/**
*KMP 字符串匹配算法核心是GetNext[]这一步,要知道在j>1时不匹配应该保证i不变,获取next[j]的值
*由字符串的比较我们可以知道我们可以保证i不变来做比较,i是不用回溯的只需回溯j的值就 可以了
*/
#include <iostream>#include <windows.h>#include <string.h>using namespace std;typedef struct{ char str[100]; int length ;}KMPString;
/**
*字符串的比较
*@param S,start ,T,next分别表示主串,开始比较的位置,字串以及next[j]的值
*@return 返回成功匹配后的v值表示成功的第一次出现的下标,如果匹配失败返回-1;
*/
int KMPIndex(KMPString S,int start,KMPString T,int next[]){cout<<"字串:"<<endl;for(int i = 0;i <T.length;i++){ cout<<T.str[i];}cout<<endl;cout<<"主串:"<<endl;for(int i = 0;i <S.length;i++){ cout<<S.str[i];}cout<<endl; int i = start; int j = 0; int count = 0; int num = 0; int v ; while(i <S.length && j <T.length){ if(S.str[i] == T.str[j]){ count++; i++; j++; } else if(j == 0){ i++; }else{ num++; j = next[j]; } } if(j == T.length){ cout<<"匹配成功!"<<endl; v = i-T.length; }else{ cout<<"匹配失败!"<<endl; v = -1; } cout <<"count="<<count<<" "<<"num = " <<num<<endl; return v; }
//获取next[j]
void GetNext(KMPString T,int next[]){// cout<<T<<endl; int j = 1;int k = 0;next[0] = 0;next[1] = 0;cout<<"T长度:"<<T.length <<endl;for(int i = 0;i <T.length;i++){ cout<<T.str[i]<<endl;}while(j < T.length){cout<<"第"<<j<<"次进入while循环"<<endl;if(T.str[j] == T.str[k]){ next[j+1] = k+1; j++; k++;}else if(k == 0){//这里是个出口,在循环后没有找到真串时,下一步跳回第一步也就是j 回溯到0 cout<<"进入k ==0"<<endl; next[j+1] = 0; j++;}else{//这里可以不断的获取到真串的存在,如果存在next[j]下一步调到j = kcout<<" k = next[k]"<<endl; k = next[k];}}for(int i = 0;i <T.length;i++){ cout<<"next["<<i<<"]="<<next[i]<<endl;} cout<<"k="<<k<<endl;}//main函数
int main(){KMPString S = {{"aaaaaaaab"},9},T = {{"aaaab"},5};//KMPString S = {{"aaaaaaaa"},8},T = {{"aaaab"},5};int next[100] ={0,1,2,3};int count = 0 ;int pos =0;cout<<"获取GetNext[j]"<<endl;GetNext(T,next);cout<<"获取next成功!"<<endl;pos = KMPIndex(S,0,T,next);if(pos >= 0){ cout<<"获取到匹配成功的位置!"<<endl; cout<<"匹配成功的位置:"<<pos<<endl; for(int i = pos ;i <S.length;i++){ cout<<S.str[i]; } cout<<endl;} system("PAUSE"); return 0;}
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- 字符串匹配的KMP算法
- openssl 证书流程和概念
- 通向架构师的道路(第五天)之tomcat集群-群猫乱舞
- linux pipd() fork() waitpid()使用实例
- 粒子群算法解决TSP问题
- Java访问https网站出现hostname wrong
- KMP 字符串的匹配算法
- stub调用WebService
- 苹果Swift编程语言入门教程【中文版】
- 通向架构师的道路(第六天)之漫谈基于数据库的权限系统的设计
- Ubuntu SMB的安装和配置
- 基本的RAID介绍
- UISegmentedControl-IOS开发
- Jetty:配置上下文
- 静与动:傅里叶变换