【数据结构】KMP算法
简介
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)(资料来源百度百科)
next[i]数组
next[i]数组是什么
next[i]数组是一个用来储存前i个字符组成的字符串的前缀和后缀相同的个数的的函数
在字符串”ABCABCACD"中,
截至为“ABCAB"除去我们所在的字符B剩下的串为
字符串"ABCA"中前缀和尾缀相同的仅为"A"
因此next[4]=1;
截至为“ABCABC"除去我们所在的字符C剩下的串为
数组"ABCAB"中前缀和尾缀相同的为"AB"
因此next[5]=2;
怎么求next[i]数组
void getnext(int next[],string *S)
{int i = 0,j=-1;next[0] = -1;//仅是我们将其定义为next[0]为-1while (i < S->length){if (j == -1 || S->str[i] == S->str[j]){i++;j++;next[i] = j;}elsej = next[j];}
}
我刚开始看的时候对求next[i]的两句话不是很理解
为什么我们要有j==-1
if (j == -1 || S->str[i] == S->str[j])
另一句是为啥是j=next[j] (重点)
j = next[j];
首先我们来讲第二句
在"ABCABCABD"中,当我们头缀尾缀匹配到B时,匹配上的已经有"ABCAB"
再接下去我们要进行匹配的是头缀的'C'和尾缀的'D',这时我们就已经匹配不上了
那此时进行j=next[j]即是令j=next[5]=2,仔细想想我们的'D'的前面的字符串有几个和头缀相同
就是next[5]个
所以我们的匹配就会接着把移到前面两个已经匹配了
如果我们的接下来的能够匹配上
假如:
这样我们就可以接着匹配了
但要是没继续匹配上
此时我们再去匹配会发现还是不匹配
所以再去看前面的头尾缀有相同的否就发现没有相同的,那么就会使得我们的匹配把j赋值为next[2]即是0
这时就是把'D'和首字符'A'进行比较
此时发现还是匹配不上那么就把j=next[0]=-1;
再回到
if (j == -1 || S->str[i] == S->str[j])
我们把这个这个拆开再去看就能够十分的明了了
if (j == -1 ){i++;j++;next[i] = j;}else if ( S->str[i] == S->str[j]){i++;j++;next[i] = j;}
else if我们能够很明了的了解到
当两个相同的时候就可以移步到下一个这样他的去除自身的头尾缀最大就可以记录下来,接着包括他自身再次进行一个匹配,如果匹配上了则进入下个接着匹配,否则则进入else 进行j=next[j]的操作
那么j==-1
第一
就是为了我们最开始的时候在j=-1和i=0能够先进入j++和i++从而对字符串的第1个(S->str[0])和第2个(S->str[1])进行对比
第二是为了在我们在我们的当前字符(这里是'D')和首字符匹配不上的时候,那么就把当前字符的next[i]赋值为0,就是没有和前面有任何匹配,同时呢,再把我们要匹配的字符往下面再移动一个和第一个字符进行匹配
由于上面的几个的都是相同的表示所以我们就把j==-1和S->str[i] == S->str[j]合并起来了
KMP算法
我们先给出一段代码
int KMP(string* T, string* S)
{int i = 0, j = 0;int next[255];getnext(&next,S);while (i < T->length){if (j == -1 || T->str[i] == S->str[j]){i++;j++;if (j == S->length)return i - j+1;}elsej = next[j];}}
首先
int i = 0, j = 0;
这边给j赋值为0就是为了最开始就进行S串和T串的匹配,如果匹配不上就把j赋值到-1,为了把我们要匹配的字符往下面再移动一个和第一个字符进行匹配(类同next的求法)
if (j == S->length)return i - j+1;
用来返回最先匹配到的字符串的首的位置
j = next[j];
和next的求法里的意思是一样的当没匹配上的时候就会进行往前去寻找有没有匹配上的个数有则接着匹配,没有则回到最开头进行下个字符的匹配
最后附上全部的代码
#include<stdio.h>
#include<string.h>
typedef struct
{char str[255];int length;
}string;
int KMP(string* T, string* S);
void getnext(int next[],string *S);
int main()
{int n;string T,S;gets(T.str);gets(S.str);T.length = strlen(T.str);S.length = strlen(S.str);n=KMP(&T,&S);printf("%d", n);return 0;
}
int KMP(string* T, string* S)
{int i = 0, j = 0;int next[255];getnext(next,S);while (i < T->length){if (j == -1 || T->str[i] == S->str[j]){i++;j++;if (j == S->length)return i - j+1;}elsej = next[j];}}
void getnext(int next[],string *S)
{int i = 0,j=-1;next[0] = -1;while (i < S->length){if (j == -1 || S->str[i] == S->str[j]){i++;j++;next[i] = j;}elsej = next[j];}
}
【数据结构】KMP算法相关推荐
- 数据结构--KMP算法总结
数据结构-KMP KMP算法用于解决两个字符串匹配的问题,但更多的时候用到的是next数组的含义,用到next数组的时候,大多是题目跟前后缀有关的 . 首先介绍KMP算法:(假定next数组已经学会, ...
- [转]数据结构KMP算法配图详解(超详细)
KMP算法配图详解 前言 KMP算法是我们数据结构串中最难也是最重要的算法.难是因为KMP算法的代码很优美简洁干练,但里面包含着非常深的思维.真正理解代码的人可以说对KMP算法的了解已经相当深入了.而 ...
- 数据结构——KMP算法(难懂版,但还是看看吧)
据说这个算法很难,起初看了<大话数据结构>,知道了这个算法,但是没看懂没理解,然后看其他博客,尽管博客上写着易懂,好理解,但我仍然看不懂,不理解,心里一直在口吐芬芳. 后来我看了几个版本的 ...
- 数据结构KMP算法配图详解(超详细)
KMP算法配图详解 前言 KMP算法是我们数据结构串中最难也是最重要的算法.难是因为KMP算法的代码很优美简洁干练,但里面包含着非常深的思维.真正理解代码的人可以说对KMP算法的了解已经相当深入了.而 ...
- 数据结构 KMP算法中next数组与nextval如何求
个人学习用,比较杂乱. 一.例题 二.题目(3)next解法见图 三. nextval如何求解? 3.1步骤一:画图,先求出next 3.2 位置1的数必定为0,记住即可 位置2的next为1,所以要 ...
- a - 数据结构实验之串一:kmp简单应用_中高级面试必备:快速入门数据结构和算法
一 前言 1 为什么要学习算法和数据结构? 解决特定问题. 深度优化程序性能的基础. 学习一种思想:如何把现实问题转化为计算机语言表示. 2 业务开发要掌握到程度? 了解常见数据结构和算法,沟通没有障 ...
- 数据结构与算法之KMP算法
数据结构与算法之KMP算法 目录 KMP算法介绍 输入字符串str1,str2,返回字符串str2是否在str1中,在的话在第几位开始 1. KMP算法介绍 在CSDN上看到一篇写的很好的关于KMP的 ...
- 数据结构与算法一篇帮助你吃下KMP算法
模式匹配 什么是模式匹配,我们用一个案例来说明: 当S = "s1,s2,s3,s4 -sn" T="t1,t2,t3,t4 - tn" 在字符串S中寻找T字符 ...
- c语言数据结构kmp中next计算,数据结构——关于KMP算法中next函数的详细解析
以前看到数据结构中字符串的模式匹配时,花了半天的时间,才把KMP算法中的next函数整明白了,结果过了几天在看到这时,只记得next[j+1]=next[j]+1,但是有时候能套公式正确算出,有时候就 ...
- 数据结构 4 字符匹配-KMP算法
第四章主要介绍的是串,但是串的实现没什么必要,最重要的知识点在于KMP算法的使用,大二时数据结构总结过一次KMP算法,大二时总结的比较细致,链接如下: https://blog.csdn.net/we ...
最新文章
- 标记三维点_细胞器相互作用过程的高速三维全景成像
- Computer:成功解决安装软件时需要系统空间环境辅助程序(比如Microsoft Visual C++2010 x86 Redistributable安装失败)
- Matlab | 数字信号处理:用FFT做谱分析
- Spring核心系列之Spring中的事务
- import org.apache.commons.codec.digest.DigestUtils; 未导入
- 如何使用exclipse打开已有的文件夹
- Qt QInputDialog文本输入对话框示例
- 信息学奥赛一本通 1982:【19CSPJ普及组】数字游戏
- java .equal_Java 中的equals()方法
- SSLOJ 1335.蛋糕切割
- C#的TextBox控件输入测试-只允许输入数字的测试:
- 数仓建模—事实表和维度表设计规范
- Vue报错信息Module not found: Error: Can‘t resolve ‘vue/types/umd‘ in
- 李沐动手学深度学习V2-RNN循环神经网络从零实现
- 数据结构和算法(Java),上
- 引导区坏 计算机无法启动,小白告诉你Win10无法正常启动修复引导文件教程
- 哪种无线耳机音质最好?盘点2023四款好音质蓝牙耳机
- 数据挖掘中的机器学习
- 《Spring系列》第15章 声明式事务(一) 基础使用
- android9机型,安卓9正式定名Android 9 Pie,这些机型可以尝鲜