模式匹配(第二篇KMP算法
来源:互联网 发布:linux 网卡网关 编辑:程序博客网 时间:2024/06/05 14:28
KMP算法是由D.E.Knuth、J.H.Morris和V.R.Pratt等人共同提出的,所以称为Knuth-Morris-Pratt算法,简称为KMP算法。KMP算法分析了模式串中隐藏的有利于模式匹配的信息。这种信息就是模式串中的“部分匹配”信息,或者,模式串中某个位置“前串等于后串”的最大长度信息。
模式串t的next[j]数组公式如下:
由此得到next[]数组的算法和KMP算法如下:
//求next[]void GetNext(SqString t,int next[]){ int j,k; j=0; k=-1; next[0]=-1; while (j<t.length-1) { if (k==-1 || t.data[j]==t.data[k]) { j++; k++; next[j]=k; } else k=next[k]; }}//KMP算法:判断s与t是否匹配int KMPIndex(SqString s,SqString t){ int next[MaxSize],i=0,j=0,v; GetNext(t,next); while (i<s.length && j<t.length) { if(j==-1 || j<t.length){ i++; j++; } else j=next[j]; } if(j>=t.length) v=i-t.length; else v=-1; return v;}
设主串
上述算法,还可以改进一下,如下:
//求NextVal[]数组void GetNextVal(SqString t,int nextVal[]){ int j=0,k=-1; nextVal[0]=-1; while(j<t.length){ if (k==-1 || t.data[j]==t.data[k]) { j++; k++; if(t.data[j]!=t.data[k]) nextVal[j]=k; else nextVal[j]=nextVal[k]; } else k=nextVal[k]; }}//修正后的KMP算法int KMPIndex1(SqString s,SqString t){ int nextval[MaxSize],i=0,j=0,v; GetNextVal(t,nextval); while (i<s.length && j<t.length) { if (j==-1 || j<t.length) { i++; j++; } else j=nextval[j]; } if(j>=t.length) v=i-t.length; else v=-1; return v;}
与改进前的KMP算法一样,本算法的时间复杂度也为
《数据结构(c语言版)》–严蔚敏,把next[j]定义如下:
该公式与前面的公式是等价的,只不过next[j]定义的起点不同,前者j从0开始,next[0]=-1,next[1]=0,…; 后者j从1开始,next[1]=0,next[2]=1,…。如图(1)所示:
完整代码如下:
//Base.h#include <stdio.h>#define MaxSize 100typedef struct{ char data[MaxSize]; int length;}SqString;//创建串void StrAssign(SqString &str,char cstr[]){ int i; for(i=0;cstr[i]!='\0';i++) str.data[i]=cstr[i]; str.length=i;}//串复制void StrCopy(SqString &s,SqString t){ int i; for(i=0;i<t.length;i++) s.data[i]=t.data[i]; s.length=t.length;}//判断串s与串t是否相同int StrEqual(SqString s,SqString t){ int same=1,i; if(s.length!=t.length) same=0; else{ for(i=0;i<s.length;i++) if(s.data[i]!=t.data[i]) same=0; } return same;}//求串长int StrLength(SqString s){ return s.length;}//两串比较SqString Concat(SqString s,SqString t){ SqString str; int i; str.length=s.length+t.length; for(i=0;i<s.length;i++) str.data[i]=s.data[i]; for(i=0;i<t.length;i++) str.data[s.length+i]=t.data[i]; return str;}//求串s中第i(1≤i≤n)个位置长度为j的子串 SqString SubStr(SqString s,int i,int j){ SqString str; int k; str.length=0; if (i<=0 || i>s.length || j<0 || i+j-1 >s.length) { printf("参数不正确\n"); return str; } for(k=i-1;k<i+j-1;k++) str.data[k-i+1]=s.data[k]; str.length=j; return str;}//在串s的第i个位置插入串s2SqString InsStr(SqString s1,int i,SqString s2){ int j; SqString str; str.length=0; if(i<=0 || i>s1.length+1) //参数不正确时,返回空串 { printf("参数不正确\n"); return s1; } for(j=0;j<i-1;j++) //将s1.data[0]~s1.data[i-2]复制到str str.data[j]=s1.data[j]; for (j=0;j<s2.length;j++) //将s2.data[0]~s2.data[s2.length-1]复制到str str.data[i+j-1]=s2.data[j]; for(j=i-1;j<s1.length;j++) //将s1.data[i-1]~s.data[s1.length-1]复制到str str.data[s2.length+j]=s1.data[j]; str.length=s1.length+s2.length; return str;}//删除串s中第i个位置长度为j的子串SqString DelStr(SqString s,int i,int j){ int k; SqString str; str.length=0; if (i<=0 || i>s.length || i+j>s.length+1) { printf("参数不正确\n"); return str; } for(k=0;k<i-1;k++) str.data[k]=s.data[k]; for (k=i+j-1;k<s.length;k++) str.data[k-j]=s.data[k]; str.length=s.length-j; return str;}//在串s中,用串t替换在第i个位置长度为j的子串SqString RepStr(SqString s,int i,int j,SqString t){ int k; SqString str; str.length=0; if (i<=0 || i>s.length || i+j-1 >s.length) { printf("参数不正确\n"); return str; } for(k=0;k<i-1;k++) str.data[k]=s.data[k]; for (k=0;k<t.length;k++) str.data[i+k-1]=t.data[k]; for(k=i+j-1;k<s.length;k++) str.data[t.length+k-j]=s.data[k]; str.length=s.length-j+t.length; return str;}//输出串strvoid DispStr(SqString str){ int i; if (str.length>0) { for(i=0;i<str.length;i++) printf("%c",str.data[i]); printf("\n"); }}//主函数.cpp#include "base.h"#include <stdio.h>/*----------------------KMP算法-------------------------*///求next[]void GetNext(SqString t,int next[]){ int j,k; j=0; k=-1; next[0]=-1; while (j<t.length-1) { if (k==-1 || t.data[j]==t.data[k]) { j++; k++; next[j]=k; } else k=next[k]; }}//KMP算法:判断s与t是否匹配int KMPIndex(SqString s,SqString t){ int next[MaxSize],i=0,j=0,v; GetNext(t,next); while (i<s.length && j<t.length) { if(j==-1 || j<t.length){ i++; j++; } else j=next[j]; } if(j>=t.length) v=i-t.length; else v=-1; return v;}/*-------------------------改进的KMP算法---------------------*///求NextVal[]数组void GetNextVal(SqString t,int nextVal[]){ int j=0,k=-1; nextVal[0]=-1; while(j<t.length){ if (k==-1 || t.data[j]==t.data[k]) { j++; k++; if(t.data[j]!=t.data[k]) nextVal[j]=k; else nextVal[j]=nextVal[k]; } else k=nextVal[k]; }}//修正后的KMP算法int KMPIndex1(SqString s,SqString t){ int nextval[MaxSize],i=0,j=0,v; GetNextVal(t,nextval); while (i<s.length && j<t.length) { if (j==-1 || j<t.length) { i++; j++; } else j=nextval[j]; } if(j>=t.length) v=i-t.length; else v=-1; return v;}void main(){ SqString str,str2; char s[20]="Helloworld"; char s2[10]="llowo"; StrAssign(str,s); StrAssign(str2,s2); //DispStr(str); printf("主串为: %s\n",s); printf("模式串为:%s\n",s2); int isPipei=0; int next[6];// GetNext(str2,next);// isPipei=KMPIndex(str,str2); GetNextVal(str2,next); isPipei=KMPIndex1(str,str2); if (isPipei != -1) { printf("匹配成功!\n"); } else{ printf("匹配失败!\n"); }}
效果如下:
模式匹配(第一篇:
http://blog.csdn.net/sanqima/article/details/48863425
- 模式匹配(第二篇KMP算法
- 模式匹配---KMP算法
- 模式匹配 KMP算法
- 模式匹配-KMP算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- 模式匹配kmp算法
- 模式匹配算法kmp
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP模式匹配算法
- KMP算法模式匹配
- java多组件时如何更新表格
- 20个位运算技巧
- Eclipse常用快捷键
- mysql主备库数据不一致的原因和解决方案(转)
- poj-2488 A Knight's Journey
- 模式匹配(第二篇KMP算法
- linux(ubuntu)系统,进入不了图形界面时,如何进入终端(命令行)?
- 异常处理(Exception)
- Java HashMap 源码解析
- Sublime Text 3 插件汇总
- 南阳oj_(34)韩信点兵
- myeclipse更改deploy location名称
- 浅拷贝、深拷贝以及拷贝构造函数
- javascript常用数组算法总结