KMP字符串模式匹配的C实现

来源:互联网 发布:少儿编程培训班招聘 编辑:程序博客网 时间:2024/05/16 19:54

申请这个BLOG很久了,可发的内容少的可怜,又一段时间没更新了,所以随便发点凑个数,呵呵。

KMP算法是字符串模式匹配的一种比较好的算法,此算法的时间复杂度为O(m+n),其中m为源字符串长度,n为目标字符串长度,此算法其实是利用目标字符串构造一个简单的自动机。因为它由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,所以人们称它为 克努特-莫里斯-普拉特操作(简称KMP算法),呵呵,第一个人非常著名,是我的偶像。

下面列出源代码清单,希望对这感兴趣的朋友与我交流。

      
/*
* Author : harly
* Date   : 2006-4-24
**/

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>

//试验KMP算法
int* computeNext(const char* pattern);  //计算模式的next数组
int stringMatch(const char* src, const char* target);//普通的模式匹配函数
void print(int* pInt , int num); //输出pInt里面的元素,num为个数
int stringMatchKmp(const char* src, const char* target);

void main()
{
    const char* src    = "abacabcacabcabcabcattcbab";
    const char* target = "abcabcabc";

    //printf("%d",strlen(""));
    //调用普通的字符串匹配函数
    printf( "src:    %s/ntarget: %s/nThe index is: %d/tBased on original algoithm/n", src, target, stringMatch(src, target) );

    //调用KMP方式实现的字符串匹配函数
    printf( "/nsrc:    %s/ntarget: %s/nThe index is: %d/tBased on KMP algorithm/n", src, target, stringMatchKmp(src, target) );

 

    getch();

}

//从字符串src中查找target串,如果找到就返回第一个匹配地位置,否则返回-1
int stringMatch(const char* src, const char* target)
{
    int srcLen , targetLen, i, j, index;
    i = j = 0;
    assert( src != NULL && target != NULL);

    srcLen = strlen(src);
    targetLen = strlen(target);

    while ( i < srcLen  &&  j < targetLen )
    {
        if (src[i] == target[j] )
        {
            i++;
            j++;
        }
        else
        {
            i = i - j +1;
            j = 0;
        }
    }
    if (j == targetLen) index = i - targetLen;
    else index = -1;

    return index;
}

int* computeNext(const char* pattern)
{

    int len , i, nextTemp;
    int *next ;

    assert(pattern != NULL);
    len = strlen(pattern);
    if (len == 0) len =1;  //应该需要这句,否则空字符串的时候就麻烦了
    next =  (int*)malloc( sizeof(int) * len );
    next[0] = -1;

    for (i = 1; i < len; i++)
    {
        nextTemp = next[i-1];
        while (pattern[i-1] != pattern[nextTemp] && nextTemp >=0 )
        {
            nextTemp = next[nextTemp];
        }
        next[i] = nextTemp +1;

    }

    return next;
}

void print(int* pInt , int num) //输出pInt里面的元素,num为个数
{
    int i;
    printf("The next is: /n");
    for (i =0; i< num; i++)
    {
        printf("%d  ", pInt[i]);
    }
}


//从字符串src中查找target串,如果找到就返回第一个匹配地位置,否则返回-1
int stringMatchKmp(const char* src, const char* target)
{
    int srcLen, targetLen;
    int i = 0, j = 0, index;
    int *next;

    assert(src != NULL && target !=NULL);
    srcLen = strlen(src);
    targetLen = strlen(target);
    next = computeNext(target);
    print(next, strlen(target) );

    while (i < srcLen && j < targetLen)
    {


           if ( j== -1 || src[i] == target[j] )
           {
             // printf("/n%c,%c,%i", src[i], target[j],j);
              i++;
              j++;
           }
           else
           {
              j = next[j];
           }


    }

    if (j == targetLen)
    {
        index = i -targetLen;
    }
    else
    {
        index = -1;
    }

    free(next);

    return index;
}

原创粉丝点击