我们要找到一个短字符串(模式串)在另一个长字符串(原始串)中的起始位置,也就是模式匹配,最关键的是找到next数组。最简单的算法就是用双层循环来解决,但是这种算法效率低,kmp算法是针对模式串自身的特点,当失配时,能够利用next数组得到的信息直接跳过不可能匹配成功的位置字符。例如模式字符串“ababaaaba”,假设当匹配到第6个字符“a”发生错误,传统方法是原始字符串往后移动一个,但是原始串显然第2个字符是b(因为之前匹配过了),不可能是模式串的起始字符,而next会发现从原始串的第1个字符开始的“aba”和第3个字符开始的“aba”是一样的,所以直接将模式串的第1个字符和原始串的往后移动2个的字符比较,而此时直接用模式串第4个字符与之前原始串中失配的字符比也就是说模式串中第6个位置和第4个位置的字符位置等价,你失配了我来,因为他们前面有相同的串,而且其中一个是从模式串的起始位置开始的,这也就是next数组的定义。

  说的这么详细是因为考研期间这个部分非常难,我本人也是用了几天才参透这里面的原理,毕竟是非常著名的算法,不是背上来代码那么简单。​​

  字符串​一般是从编号1开始,第0个位置存放长度,简单起见下面的代码简化表示。

#define _CRT_SECURE_NO_DEPRECATE//vs编译器编译c语言需要加此条语句
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void get_next(int *next, char *Array,int len) /*求NEXT[]的值*/
{
	int i = 1, j = 0;  //如果字符串不是从编号1开始,则初始化i=0,j=-1
	next[1] = 0;//初始化第一个字符的next值为0
	while (i < len)//整个过程中i变量一遍走过,而j变量可能会回溯,i一直在j后面
	{
		if (j == 0 || Array[i] == Array[j])//起始或者字符有重复,那么下一个位置i++和j++的位置等价,
		{
			i++;
			j++;
			if (Array[i] == Array[j])//如果从此行开始的三行去掉,则是未改进的kmp算法
				next[i] = next[j];   //优化找到最开始的等价位,等价位的等价位
			else
				next[i] = j;
		}
		else
			j = next[j];  //回溯,正是利用了next数组本身的回溯的功能
	}
}
int main()
{
	char A[] = "0ababaaaba";//为了使得字符数据从编号1开始
	int next[sizeof(A)-1] = { 0 };//初始化
	int len = sizeof(A)-1;
	get_next(next, A,len);
	for (int i = 1; i < len;i++)
		printf("%d ",next[i]);
	system("pause");//vs运行需要加此条代码
	return 0;
}

  运行结果:​若为未改进的算法,模式串“ababaaaba”的next运行结果为

  0 1 1 2 3 4 2 2 3,

  改进算法运行结果为0 1 0 1 0 4 2 1 0。

  考试题也有可能不考代码,我的经验是先根据算法写出为改进的,然后从头开始对应的字符一样就改为前面那个字符的next值,以此类推。​

数据结构之KMP算法next数组的更多相关文章

  1. KMP算法&next数组总结

    http://www.cnblogs.com/yjiyjige/p/3263858.html KMP算法应该是每一本<数据结构>书都会讲的,算是知名度最高的算法之一了,但很可惜,我大二那年 ...

  2. 【数据结构】KMP算法

    我还是不太懂... 转2篇大神的解释    1>https://www.cnblogs.com/yjiyjige/p/3263858.html     2>https://blog.csd ...

  3. 转载-KMP算法前缀数组优雅实现

    转自:http://www.cnblogs.com/10jschen/archive/2012/08/21/2648451.html 我们在一个母字符串中查找一个子字符串有很多方法.KMP是一种最常见 ...

  4. 基础数据结构-串-KMP算法

    KMP算法用于模式串字符匹配,因为没有提前预习,上课时听得云里雾里,后来回去看了一晚上,翻了一些网上的讲解才理解了.我简单讲一下,我们在一串字符串A里搜索匹配另一段字符串B时,思路最简单方法的就是从第 ...

  5. KMP算法 Next数组详解

    题面 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百 ...

  6. 第4章学习小结_串(BF&KMP算法)、数组(三元组)

    这一章学习之后,我想对串这个部分写一下我的总结体会. 串也有顺序和链式两种存储结构,但大多采用顺序存储结构比较方便.字符串定义可以用字符数组比如:char c[10];也可以用C++中定义一个字符串s ...

  7. KMP算法next数组求解

    关于KMP算法,许多教材用的是递推式求解,虽然代码简洁,但是有些不好理解,这里我介绍一种迭代求next数组的方法 KMP算法关键部分就是滑动模式串,我们可以每次滑动一个单位,直到出现可能匹配的情况,此 ...

  8. 【文文殿下】浅谈KMP算法next数组与循环节的关系

    KMP算法 KMP算法是一种字符串匹配算法,他可以在O(n+m)的时间内求出一个模式串在另一个模式串下出现的次数. KMP算法是利用next数组进行自匹配,然后来进行匹配的. Next数组 Next数 ...

  9. poj1961(kmp算法next数组应用)

    题目链接:https://vjudge.net/problem/POJ-1961 题意:给定一个长为n的字符串(n<=1e6),对于下标i(2<=i<=n),如果子串s(1...i) ...

随机推荐

  1. opencv学习

    判断是否正确读入的方法: if( argc != 2 || !(src=imread(argv[1], 1)).data ) return -1; --- if( src.empty() ) { re ...

  2. Win7旗舰版-X86-X64-快速装机版

    装机版作品简介 Win7 32/64位旗舰版 6.5z 专注于Win7,致力于做更好用的系统!一如既往的品质,不流氓,不欺骗,不夸大!一直在改进,只为做得更好!万千用户的信赖,作者的品质保证! 作品摘 ...

  3. Acer-宏碁电脑BOIS

    进入电脑BOIS界面; 1.开机(一闪而过)注意第一屏左下角,会有进入BIOS按键提示. 2.如一开机没有进入BIOS的键值提示,取而代之的是品牌机的Logo,可参阅以下列表:不是品牌机可参阅主板设置 ...

  4. React.js入门笔记(续):用React的方式来思考

    本文主要内容来自React官方文档中的"Thinking React"部分,总结算是又一篇笔记.主要介绍使用React开发组件的官方思路.代码内容经笔者改写为较熟悉的ES5语法. ...

  5. CSS大杂烩(1)

    box-sizing 有4种方式 border-box 用来减去padding内边框和边框 前提是设置好固定宽高 content-box 在宽和高之外内边距和边框 其实基本上和原来一样 inherit ...

  6. tyvj1203 机器分配

    描述 总公司拥有高效生产设备M台,准备分给下属的N个公司.各分公司若获得这些设备,可以为国家提供一定的盈利.问:如何分配这M台设备才能使国家得到的盈利最大?求出最大盈利值.其中M<=100,N& ...

  7. LYDSY模拟赛day2 Dash Speed

    /* 弃坑 */ #include<cstdio> #include<algorithm> using namespace std; ,M=N*; ],nxt[N<< ...

  8. [Git] Git基础

    远程仓库 查看远程仓库: git remote -v 添加远程仓库: git remote add <repoName> <url> 拉取远程仓库数据: git fetch & ...

  9. Linux C 中 fork() 函数详解

    一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork() 函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同 ...

  10. .htaccess 基础教程(四)Apache RewriteCond 规则参数

    Apache模块 mod_rewrite 提供了一个基于正则表达式分析器的重写引擎来实时重写URL请求.它支持每个完整规则可以拥有不限数量的子规则以及附加条件规则的灵活而且强大的URL操作机制.此UR ...