KMP算法next & nextval探讨

来源:互联网 发布:rar压缩软件mac版 编辑:程序博客网 时间:2024/06/06 19:48

摘要:本文在阅读清华大学教授严蔚敏《数据结构》一书的基础上,同时参照互联网上已有KMP相关文章的前提下,对KMP匹配过程中next与nextval数组的计算,做了图形化探讨。并一句话概括计算原则——计算next[j]函数值,必从j-1位置开始(不是j),以j-1为节点号,next[j-1]为链表尾指针,一直往前查找,直到找到与arr[j-1]值相同的位置时(k)停止,则此时next[j]=next[k]+1。(注:将上述表格抽象为链表,从后往前的链表)。


目录:

  • 何为KMP算法模式匹配的一种改进算法
  • next函数值计算
    • 示例next5求法
    • 示例next3求法
  • nextval函数值计算
  • 附nextnextval测试

何为KMP算法——模式匹配的一种改进算法

这种算法是D.E.Knuth与V.R.Pratt和J.H.Morris同时发现的,因此人们称它为克努特—莫里斯—普拉特算法(简称为KMP算法)。此算法可以在O(m+n)的时间数量级上完成串的模式匹配操作。

其改进在于:每当一趟匹配过程中出现字符比较不等时,不需要回溯 i 指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的距离后,继续进行比较。

next函数值计算

模式串的next函数定义:

这里写图片描述

由此定义可推出下列模式串的next函数值:

这里写图片描述

计算next总原则(非常重要):

计算next[j]函数值,必从j-1位置开始(不是j),以j-1为节点号,next[j-1]为链表尾指针,一直往前查找,直到找到与arr[j-1]值相同的位置时(k)停止,则此时next[j]=next[k]+1。(注:将上述表格抽象为链表,从后往前的链表)

  • 务必准确把握——j、模式串、next[j]的不同含义,不要搞混了。

几大注意事项:

  1. next[0]一般不使用,直接将next[1]=0,next[2]=1,j从1开始,j和next[j]有一一对应关系;(注:如果非要使用next[0]的话,则置next[1]=-1,next[2]=0)

  2. 一个特殊状态,如果按照上述总原则,无法找到与arr[j-1]值相同的位置。则一律置next[j]=1。

为了形式化,首先,将上述表格转化为双亲表示法树状结构如下:

这里写图片描述

示例next[5],求法;

1.表格求解法如下:

这里写图片描述

2.双亲节点表示法,求解过程如下:

这里写图片描述

示例next[3],求法;

这里写图片描述

以下留下几个表格,供手动模拟练习一下计算过程:

这里写图片描述

nextval函数值计算

前面定义的next函数在某些情况下尚有缺陷(进行了某些不必要的匹配,如下图)。为了解决该问题引入了nextval对next进行修正。

这里写图片描述

接下来继续使用上述,问题为材料对next进行修正:

这里写图片描述

在计算出next之后,得出nextval十分之简单,用以下代码表示更直接:

if (arr[j]==arr[next[j]]){    next[j] = next[next[j]];}

就是判断arr[j]与其next[j]所对应的arr[next[j]]是否相同,相同则修正,否则不需要修正。

附next/nextval测试:

#include <stdio.h>  int next[9];  //不修正  int getNextj(char arr[], int j){      int k = j-1;      while (k > 0){          //③比较arr[j-1]是否等于arr[next[j-1]]          if (arr[j-1]==arr[next[k]]){              return next[k]+1;          }          //④不等于,继续找下去          k = next[k];      }      //⑤未找到,恒置1      return 1;  }  //修正  void getNextVal(char arr[]){      int j;      for (j = 1; j < 9; ++j){          //⑥修正,如果arr[j]==arr[next[j]]则修正          if (arr[j]==arr[next[j]]){              next[j] = next[next[j]];          }      }  }  int main(void){      char arr[] = " abaabcac";//前面有一空格,T[]从1开始      int j;      //①初始化      next[1] = 0;      next[2] = 1;      //②逐个求next      for ( j = 3; j <= 8; ++j ){          next[j] = getNextj(arr,j);      }      //打印      printf("----next---\n");      for ( j = 1; j <= 8 ;++j){          printf("%d ",next[j]);      }      //修正      getNextVal(arr);      printf("\n----nextval---\n");      for ( j = 1; j <= 8 ;++j){          printf("%d ",next[j]);      }      printf("\n");      return 0;  }  

—-next—
0 1 1 2 2 3 1 2
—-nextval—
0 1 0 2 1 3 0 2
Press any key to continue

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 高三的孩子厌学怎么办 二年级小孩学习笨怎么办 孩子高二不想上怎么办 高三孩子玩手机怎么办 孩子考试粗心丢题怎么办 工作中总出错是怎么办 工作上做错事了怎么办 惹她不开心了怎么办 惹到别人不开心怎么办 孩子高三不愿意写作业怎么办? 小孩特别懒不爱学习怎么办 小孩上三年级不爱学习怎么办 一年级孩子做题粗心怎么办 一年级的孩子做题粗心怎么办 一年级娃娃做题粗心怎么办 有同学抄作业该怎么办 同学要抄我作业怎么办 同桌抄我作业我该怎么办 孩子想换同桌老师不同意怎么办 尴尬的事情心里难受怎么办 孩子撒谎不完成作业怎么办 孩子撒谎不交作业怎么办 孩子不爱写作业撒谎怎么办 大便又粗又硬怎么办 二年级末考紧张怎么办 孩子粗心做数学题老出错怎么办 生地会考考了140怎么办 数学成绩考砸了怎么办? 考砸了家长发火怎么办 大型考试考砸了怎么办 能力考试考砸了怎么办 考砸了老师批评怎么办 英语抽测考砸了老师怎么办? 辅导班学生考砸了老师怎么办 好学生考砸了怎么办? 孩子学习不认真马虎怎么办 孩子做作业不认真马虎怎么办 一年级小孩学习不认真怎么办 孩子做题审题不认真怎么办 初二孩子不认真审题怎么办 孩子总是粗心抄错题看错题怎么办