串--->KMP简单实现

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:[email protected]

猜你喜欢

转载自blog.csdn.net/qq_32603745/article/details/53264632
今日推荐