失配位置-最大相同子串(配成功的串里找,失配下标之前的子串)-1=k(移动距离)


规定:

next[1] = next[0] = 0

next[j]:j是失配位置,所以找模式串中的相同子串(前缀和后缀相等)要从j前找


前缀是:假设失配位置时j,前缀是不包含最后一个字符的字符串

后缀不包含的一个字符串

定义:

Pi表示模式P的前i个字符组成的前缀, next[i] = j表示Pi中的开始j个字符和末尾j个字符是一样的,而且对于前缀Pi来说,

这样的j是最大值。next[i] = j的另外一个定义是:有一个含有j个字符的串,它既是Pi的真前缀,又是Pi的真后缀

 

我就是发个我的作业:详细的可以看 http://kenby.iteye.com/blog/1025599 里面有较为细节的kmp整体的理解

我刚完全理解,对于描述还很欠缺,大家可以看看大神的文章


 

#include<stdio.h> // EOF(=^Z或F6),NULL

#include<stdlib.h> // srand( ) ,rand( ),exit(n)

#include<malloc.h> // malloc( ),alloc( ),realloc( )等

#include<limits.h> // INT_MAX等

#include<string.h>

#include<ctype.h>

#include<math.h> // floor(),ceil( ),abs( )

#include<time.h> // clock( ),CLK_TCK,clock_t

#include<iostream>

#define    TRUE          1

 #define     FALSE        0

 #define     OK              1

 #define     ERROR      0

 #define     INFEASIBLE     -1

#define MAXLEN 255    //串最大长度

using namespace std;

 

 

 

typedef struct

 { char  ch[MAXLEN+1];                                         //存储串的一维数组

     int   length;             //串的当前长度

   }SString;

 

void get_next(SString T, int next[])

{

    int  i= 1; next[1] = 0; int j = 0;

     while( i<T.length)

         {

             if(j==0 || T.ch[i] == T.ch[j])

               {

                  ++i;

                  ++j;

                  next[i] = j;

                }

            else     j = next[j];

         }

}

 

 

 

int Index_KMP (SString S,SString T, int pos,int next[])

{

    int i= pos,j =1;

    while (i<=S.length && j<T.length )   // ‘=’表示搜索到串尾

            /* j<=修改为< ;原因是字符串下标从1开始

            (不是0,等于将模式串串长加1(有效字符串串长不变),所以临界值减1)*/

        {  

            if (j==0 || S.ch[i]==T.ch[j]) {   i++;j++;  }

              else  j=next[j];      /*i不变, j后退*/

           }

     if(j==T.length)  //同理>改为=;很简单,T.length变大啦(+1)

     {

         return i-T.length+1;    /*匹配成功*/

            //这里+1是一样的(和下标从0开始无关,因为本书算法是从下标1开始设计的!)

            //答案同样,因为  T.length变大啦(+1啦),多减去的再加回来!   啊哈!不要崇拜我哦

     }

     else

     {

     return 0;         /*返回不匹配标志*/

     }

}

//acabaabaabcacaabc        本书测试数据

//abaabcac

 

int main()

{

int next[MAXLEN];

int nextval[MAXLEN];        //没什么用吧...待更

memset(next,0,sizeof(next));

memset(nextval,0,sizeof(nextval));     

     //memset:c++,c;置0,相当于for循环迭代数组赋值为0,更多的请问我的维基百科大哥

 

SString S, T;     //s主串!

printf("请输入主串:\n");

cin>>S.ch+1;                 //下标1开始

printf("请输入模式串:\n");

S.length=strlen(S.ch);

cin>>T.ch+1;

T.length=strlen(T.ch);

cout<<T.length<<endl;

get_next(T,next);

for(int i=0;i<T.length;i++)             //没啥用,就是看看next数组对不对

    {

        printf("%d ",next[i]);

    }

int t=Index_KMP ( S,T, 1/*pos*/,next);    //pos =1 开始

if(t)

{

printf("匹配成功!");

printf("模式串匹配位置:%d\n",t);

}

else

{

printf("匹配失败!\n");

}

getchar();

getchar();

 

}

 

 

 

 结果:

9为模式串串长!(下标从1开始,0下标无数据)

0 0 1 1 2 2 3 1 2为next数组

6为匹配成功的位置!

 

 

 

5为模式串串长!(下标从1开始,0下标无数据)

00111为next数组

5为匹配成功的位置!

 


点赞(2)
 

0.0分

0 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论