KMP的简单实现
算法介绍
使用前序遍历输入并创建
创建遍历
next数组
nextVal数组
KMP及KMP改良
第一次代码实现——–2016年-11月-8号 ———–
主函数
/*
(1)输入数据用顺序存储结构建立目标串和模式串。
(2)采用朴素匹配算法进行模式匹配。
(3)采用KMP 算法进行匹配。
(4)采用改进版KMP算法进行匹配。
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define OK 1
#define ERROR 0
#define MAXSIZE 100
typedef char String[MAXSIZE+1];
typedef int Status;
typedef int ElemType;
/* 函数声明 */
Status StrAssign(String T, char *s);
void getNext(String T, int *next);
void getNextVal(String T, int *next);
void NextPrint(int next[],int length);
int Index(String S, String T, int pos);
int IndexKMP(String S, String T, int pos);
int IndexKMP2(String S, String T, int pos);
int main(){
int i, *next;
String s1,s2;
StrAssign(s1,"abcaabab");
StrAssign(s2,"abab");
printf(" 主串为: ");
for(i = 1; i <= s1[0]; ++i)
printf("%c",s1[i]);
printf("\n");
printf(" 子串为: ");
for(i = 1; i <= s2[0]; ++i)
printf("%c",s2[i]);
printf("\n");
next = (int*)malloc( s2[0] * sizeof(int) );
getNext(s2, next);
printf(" next为: ");
NextPrint(next,s2[0]);
getNextVal(s2,next);
printf("nextVal为: ");
NextPrint(next,s2[0]);
printf("主串和子串在第%d个字符处首次匹配(朴素模式匹配算法)\n",Index(s1,s2,1));
printf("主串和子串在第%d个字符处首次匹配(KMP算法) \n",IndexKMP(s1,s2,1));
printf("主串和子串在第%d个字符处首次匹配(KMP改良算法) \n",IndexKMP2(s1,s2,1));
return 0;
}
Status StrAssign(String T, char *s){
int i;
if(strlen(s) > MAXSIZE)
return ERROR;
else
{
T[0] = strlen(s);
for(i = 1; i <= T[0]; ++i)
T[i] = *(s+i - 1);
return OK;
}
}
/* 计算子串的 next 数组 */
void getNext(String T, int *next){
int i = 1;
int j = 0;
next[1] = 0;
while(i < T[0]){
if( (j == 0) || T[i] == T[j]){
++i;
++j;
next[i] = j;
}else{
j = next[j];
}
}
return ;
}
/* 改良后的求 next 数组 */
void getNextVal(String T, int *nextVal){
int i = 1;
int j = 0;
nextVal[1] = 0;
while(i < T[0]){
if( (j == 0) || T[i] == T[j]){
++i;
++j;
if(T[i] != T[j])
nextVal[i] = j;
else
nextVal[i] = nextVal[j];
}else{
j = nextVal[j];
}
}
return ;
}
/* 打印 next 数组 */
void NextPrint(int next[],int length)
{
int i;
for(i=1;i<=length;i++)
printf("%d",next[i]);
printf("\n");
}
/*朴素模式匹配 算法*/
int Index(String S, String T, int pos){
int i = pos;
int j = 0;
while( i <= S[0] && j <= T[0]){
if(S[i] == T[j]){
++i;
++j;
}else{
i = i - j +2;
j = 1;
}
}
if( j > T[0])
return i - T[0];
else
return 0;
}
/* KMP模式匹配 算法 */
int IndexKMP(String S, String T, int pos){
int i = pos; /* i 用于主串S中 当前位置的下标, 若 pos 不为 1, 则从pos位置开始匹配 */
int j = 1; /* j 用于子串T中 当前位置 下标值 */
int next[100]; /* 定义 一 next 数组 */
getNext(T, next); /* 对串T作分析, 得到 next数组 */
while(i <= S[0] && j <= T[0]) /* 若 i 小于 S的长度并且 j 小于 T 的长度时, 循环继续 */
{
if(j == 0 || S[i] == T[j]) /* 若 两字母相等则继续, 与朴素算法增加了 j = 0 的判断*/
{
++i;
++j;
}else{ /* 否则 指针回退 重新开始 匹配 */
j = next[j]; /* j 退回到 合适的位置, i 值不变 */
}
}
if(j > T[0])
return i - T[0];
else
return 0;
}
/* 改良 KMP模式匹配 算法 */
int IndexKMP2(String S, String T, int pos){
int i = pos; /* i 用于主串S中 当前位置的下标, 若 pos 不为 1, 则从pos位置开始匹配 */
int j = 1; /* j 用于子串T中 当前位置 下标值 */
int next[100]; /* 定义 一 next 数组 */
getNextVal(T, next); /* 对串T作分析, 得到 next数组 */
while(i <= S[0] && j <= T[0]) /* 若 i 小于 S的长度并且 j 小于 T 的长度时, 循环继续 */
{
if(j == 0 || S[i] == T[j]) /* 若 两字母相等则继续, 与朴素算法增加了 j = 0 的判断*/
{
++i;
++j;
}else{ /* 否则 指针回退 重新开始 匹配 */
j = next[j]; /* j 退回到 合适的位置, i 值不变 */
}
}
if(j > T[0])
return i - T[0];
else
return 0;
}
仅供参考 ,有错误望指出.
有大神路过请指点一下。 菜鸟求飞 !!!
有什么疑问 也可以在 下边 提问 ! (有点托大了)或者发邮件
E-Mail:ppbboddqq.qq@qq.com