KMP模式匹配算法实现

来源:互联网 发布:php include 来源 编辑:程序博客网 时间:2024/05/23 00:09

/** \brief  KMP模式匹配
 *
 * \param
 * \param
 * \return
 *
 */


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


/***************************************************
*如果START_INDEX为1,则表示:本程序中字符数组从1号元素开始存储字符,0号元素存储字符的长度
*如果START_INDEX为0,则表示:本程序中字符数组从0号元素开始存储字符,数组以'\0'结尾
***************************************************/
#define START_INDEX 0   //0 or 1


#if START_INDEX==0


#define CHAR_NUM 1000   //最大支持CHAR_NUM个字符


#endif // START_INDEX


#if START_INDEX==1
/***************************************************
*如果当前元素的前K个字符与模式串中最靠近当前元素 *
*的K个字符字串完全相同那么当前元素的next值就是K+1*
***************************************************/
int get_next(char *Tstring,int *next)
{
    int i=1,j=0;    //j指向字串中当前比对到的元素,其本质是下标
    next[1]=0;  //规定第一个元素的next值为0
    while(i<(Tstring[0]-0x30))
    {


        if(j==0||Tstring[i]==Tstring[j])  //如果当前的元素与上述注释中提到的字串后一个字符也匹配
        {
            next[++i]=j+1;//此时,上述注释中的字串元素个数K增加1,i加1(向后一个字符检索),而当前next值等于字串最后一个字符的next值加1
            j++;//字串向后一个字符检索
        }
        else    //如果不等
        {
            j=next[j];  //j指向字串中当前元素的next值指向的字符(字串的字串)
        }
        /*另一种写法
        if(j==0||Tstring[i]==Tstring[j])
        {
            j++;
            i++;
            next[i]=j;
        }
        else
            j=next[j];
        */
    }
}


/*********************************************
*先计算模式串的next数组
*如果比对成功则继续比较
*如果比对失败模式串则滑动到next[j]处继续
**与主串当前元素比较
*********************************************/
int KMP(char *s,char *t)
{
    int i=1,j=1;
    int *next=(int *)malloc((t[0]-0x30+1)*sizeof(int));
    get_next(t,next);
    puts("比对顺序依次为:\n");
    while(i<=s[0]&&j<=(t[0]-0x30))
    {


        if(j==0||s[i]==t[j])
        {
            printf("%d\t%d\n",i,j);
            i++;
            j++;
        }
        else
            j=next[j];


    }
    free(next);
    if(--j==(t[0]-0x30))
        return i-j;
    else
        return -1;
}




int main()
{
    int i,index;
    char *t="8ababdabc";
    char s[]={17,'d','v','h','v','b','a','b','a','b','d','a','b','c','a','s','x','z'};
    index=KMP(s,t);
    printf("\n%d\n",index);
    return 0;
}


#endif // START_INDEX


#if START_INDEX==0
int get_next(char *Tstring,int *next)
{
    int i=0,j=-1;
    next[0]=-1;
    while(Tstring[i]!='\0')
    {


        //if(j==-1||Tstring[i]==Tstring[j])
        if(j==-1)
        {
            i++;
            j++;
            next[i]=j;
        }
        else
        {
            if(Tstring[i]==Tstring[j])
            {
                i++;
                j++;
                next[i]=j;
            }
            else
                j=next[j];
        }
    }
    return 0;


}


int KMP(char *s,char *t)
{
    int i=0,j=0;
    int next[CHAR_NUM];
    get_next(t,next);


    /*int m=0;
    while(t[m]!='\0')
        printf("%d\t",next[m++]);*/
    puts("比对顺序:\n");
    while(s[i]!='\0')
    {
        if(j>=0&&t[j]=='\0')//next[0]=-1,所以j==-1的情况是存在的
            break;
        if(j==-1||s[i]==t[j])
        {
            i++;
            j++;
        printf("%d\t%d\n",i,j);
        }
        else
        {
            j=next[j];
            //printf("hello world!\n");
        }
    }
    if(t[j]=='\0')
        return i-j+1;
    return -1;
}


int main()
{
    int i,index;
    char *t="ababdabc";
    char s[]={'d','v','h','v','b','a','b','a','b','d','a','b','c','a','s','x','z','\0'};
    index=KMP(s,t);
    printf("\n%d\n",index);
    return 0;
}


#endif // START_INDEX
0 0