KMP算法之前需要说一点串的问题:

字符串:ASCII码为基本数据形成的一堆线性结构。

串是一个线性结构;它的存储形式:

typedef struct STRING {

  CHARACTER *head;

  int length;

};

朴素的串匹配算法:

设文本串text = "ababcabcacbab",模式串为patten = "abcac"     其匹配过程如下图所示。

黑色线条代表匹配位置,红色斜杠代表失配位置

算法说明:

一般匹配字符串时,我们从目标字符串text(假设长度为n)的第一个下标选取和patten长度(长度为m)一样的子字符串进行比较,如果一样,就返回开始处的下标值,不一样,选取text下一个下标,同样选取长度为n的字符串进行比较,直到str的末尾(实际比较时,下标移动到n-m)。在普通的匹配中,假如从文本串的第i个字符来开始于模式串匹配。当匹配到模式串的第j位发现失配,即text[i+j] != patten[j]的时候,我们又从文本串的第i+1个位置来重新开始匹配。尽管我们已经知道了好多字符其实根本就匹配不上,我们还是进行了这个过程,这个时候回溯的过程会非常耗费我们的时间。这样的时间复杂度是O(n*m)

代码如下:

int search(const char*str,const char *subStr) {
int strlen = strlen(str);
int subStrlen = strlen(subStr);
int i;
int j;
for(i = ;i <= strlen - subStrlen;i++){
for(j = ;j < subStrlen;j++){
if(str[i + j] != subStr[j])
break;
}判断subStrlen是否比较完成
}
}

KMP算法:

而KMP算法的实质就是,当遇到text[i+j] != patten[j]的时候,但是我们知道模式串中的 0~j-1 位置上的字符已经于i ~ i+j-1位置上的字符是完全匹配的。就不再重新从text[i+1]开始匹配,而是根据next数组的下标找到patten的下标,从那个下标开始匹配。从而时间复杂度为O(m+n)。

例如模式串Patten = "abaabcac"。其next数组如图所示:

我们可以看到这次的匹配在蓝色的c失配了,而c的下标为5,他的next数组的下标为2。因此,下次的匹配不再是从text[1]开始,而是从text[2]开始,这样就省去了不必要的比较。

代码如下:

#include <stdio.h>
#include <malloc.h>
#include <string.h> #include "kmpmec.h" void getNext(const char *str, int *next);
int KMPSearch(const char *str, const char *subStr); int KMPSearch(const char *str, const char *subStr) {
int strLen = strlen(str);
int subLen = strlen(subStr);
int *next;
int i = ;
int j = ; if (strLen <= || subLen <= || strLen < subLen) {
return -;
}
next = (int *) calloc(sizeof(int), subLen);
if (subLen > ) {
getNext(subStr, next);
} while (strLen - i + next[j] >= subLen) {
while (subStr[j] != && str[i] == subStr[j]) {
i++;
j++;
}
if (subStr[j] == ) {
free(next);
return i - subLen;
} else if (j == ) {
i++;
j = ;
} else {
j = next[j];
}
} free(next);
return -;
} void getNext(const char *str, int *next) { //得到next数组
int i = ;
int j = ;
boolean flag; next[] = next[] = ; //next数组的前两个下标一定为零
for (i = ; str[i]; i++) {
for (flag = TRUE; flag;) {
if (str[i-] == str[j]) { //通过比较失配位置的前一个和前一个下标元素的比较,获取next数组的下标。
next[i] = ++j;
flag = FALSE;
} else if (j == ) {
next[i] = ;
flag = FALSE;
} else {
j = next[j];
}
}
}
} int main(void) {
char str[];
char subStr[];
int result; printf("请输入源字符串:");
gets(str);
printf("请输入子字符串:");
gets(subStr); result = KMPSearch(str, subStr);
if (result == -) {
printf("字符串[%s]不存在子串[%s]\n", str, subStr);
} else {
printf("子串[%s]第一次出现在字符串[%s]中的下标为%d\n", subStr, str, result);
} return ;
};

KMP算法(next数组方法)的更多相关文章

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

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

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

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

  3. KMP算法next数组求解

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

  4. 数据结构之KMP算法next数组

    我们要找到一个短字符串(模式串)在另一个长字符串(原始串)中的起始位置,也就是模式匹配,最关键的是找到next数组.最简单的算法就是用双层循环来解决,但是这种算法效率低,kmp算法是针对模式串自身的特 ...

  5. KMP算法&next数组总结

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

  6. KMP算法 Next数组详解

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

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

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

  8. KMP算法(推导方法及模板)

    介绍 克努斯-莫里斯-普拉特算法Knuth-Morris-Pratt字符串查找算法(简称为KMP算法)可在一个主文本字符串S内查找一个词W的出现位置.此算法通过运用对这个词在不匹配时本身就包含足够的信 ...

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

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

  10. POJ-2752(KMP算法+前缀数组的应用)

    Seek the Name, Seek the Fame POJ-2752 本题使用的算法还是KMP 最主要的片段就是前缀数组pi的理解,这里要求解的纸盒pi[n-1]有关,但是还是需要使用一个循环来 ...

随机推荐

  1. JavaScript实现全选功能

    最终效果: 代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...

  2. 关于使用spring mvc或者resteasy构建restful服务的差别与比较

    resteasy 是 jboss的一个开源java api for restful service(JSR 311,sun 2008年发布,最新GA版本是2.0, JAX-RS 2.0 (JSR-33 ...

  3. webstorm 安装与基本使用

    1.1 webstorm 安装与配置 1.安装: https://blog.csdn.net/jiangxinyu50/article/details/79104016 2.使用: https://w ...

  4. UI自动化(一)html基础

    前端的三把利器 HTML:赤裸的一个人 CSS:华丽的衣服 JS/JavaScript:赋予这个人的行为,也就是动起来 DOM 就是将页面变成可操 HTML(超文本标记语言) html代码实际上就是一 ...

  5. JQuery 实现 倒计时 按钮具体方法

    <head> <title>test count down button</title> <script src="http://ajax.aspn ...

  6. wait()和notify()的理解与使用

    void notify() Wakes up a single thread that is waiting on this object’s monitor. 译:唤醒在此对象监视器上等待的单个线程 ...

  7. 89. a^b【快速幂模板】

    a^b Description 求 aa 的 bb 次方对 pp 取模的值. 输入格式 三个整数 a,b,pa,b,p ,在同一行用空格隔开. 输出格式 输出一个整数,表示a^b mod p的值. 数 ...

  8. gimp的使用笔记

    gimp是德国的开源软件! 跟其他软件一样, 包括file, edit, view, 还有select, color , filter, 和 window. 窗口window就包括所有的dockabl ...

  9. Linux 题目收集

    目录 1.库函数,系统调用,用户态及内核态 2.查看进程,杀死进程 3.查看文档 4.scp命令 5.不在 sudoers 文件中.此事将被报告 6.chmod: 更改"minikube&q ...

  10. 【做题】zoj3649 Social Net——倍增

    这题是吴老师推荐的,于是我就去做了. 根据题意,在完成最大生成树后,对于树上从x到y的一条路径,求出最大的ck-cj(j<=k,ci为路径上第i个点的权值). 我一开始的想法是二分,记路径xy的 ...