Kmp算法浅谈

一.Kmp算法思想

在主串和模式串进行匹配时,利用next数组不改变主串的匹配指针而是改变模式串的匹配指针,减少大量的重复匹配时间。在Kmp算法中,next数组的构建是整个Kmp算法的核心所在。

二.Kmp核心之next数组的构建

(1)前缀,后缀的定义

(2)最长公共前后缀定义

(3)next数组的含义

next数组代表各个长度子串(这些字串的起始位置都为0)的最长公共前后缀长度,为了方便代码的编写next[0]定为-1,表示前0个字符根本不存在前后缀这一说法。其他的例如next[1]表示前一个字符的 最长公共前后缀 ,很明显根据前后缀的定义,next[1]=0;next[1]和next[0]在本博客说明的next数组构成中是唯一和确定的。

(4)最长公共前后缀定义及与next的联系

(5)对于一个模式串next数组到底能表示什么

首先根据上面的说法next数组表示了模式串长度为i的前缀的最长公共前后缀的的长度,所以说next可以来表示长度。这个时候我们在深究一下它表示的是谁的长度?它表示的是最长公共前后缀的!!!!,也就是说它可以表示模式串中第next[i]个元素的下标!!!,不懂的话看图就明白了

(6)如何利用next数组的性质避免重复匹配呢

三.如何用代码的形式得到next数组

首先上个代码

void Getnext(int next[],char *MyString)
{
int j=,k=-;
next[]=-;//规定,方便后面k的计算
while(j<strlen(MyString)-)//j不能超过整个串的长度
{
//j为当前字符,k为j前面那些字符的最长公共前后缀的下一个字符
if(k == - || MyString[j] == MyString[k])next[++j] = ++k;
//模式串的第一个字符就要比较的字符不一样,那我就要将模式串的下一个字符和我要比较的字符比较,且现在k还是为-1的,所以++j,++k
else k = next[k];
}
}
 

三.Kmp算法代码

得到了next后一切就简单了,无非就是设定两个“指针”分别指向主串和模式串,当出现不匹配时模式串的指针根据next数组移动就好了,直接上代码

int Kmp(char *T,int numt,char *P,int nump,int *next)//T为主串,P为模式串
{
int i=,j=;//i为主串的指针,j为模式串的指针
while(i<=numt-nump)
{
while((T[i]==P[j]&&i<numt)||j==-) ++i,++j;//j==-1
//模式串第一个就和主串中要匹配的字符不匹配,主串字符后移一位,模式串的指针也从-1恢复到零
if(j==nump)//找到匹配串
return i-nump;//返回在主串中的起始位置
j=next[j];
}
return -;//表示无法找到
}
 

四.整个程序完整代码

#include <stdio.h>
#include <string.h>
void Getnext(int next[],char *MyString);
int Kmp(char *T,int numt,char *P,int nump,int *next);
const int SIZE=;
int main()
{
char *T=new char[SIZE];
char *P=new char [SIZE];
int *next=new int [SIZE];
scanf("%s",T);
scanf("%s",P);
Getnext(next,P);
for(int i=;i<strlen(P);i++) printf("%d,",next[i]);
printf("\n%d",Kmp(T,strlen(T),P,strlen(P),next));
return ;
}
void Getnext(int next[],char *MyString)
{
int j=,k=-;
next[]=-;
while(j<strlen(MyString)-)
{
if(k == - || MyString[j] == MyString[k])next[++j] = ++k;
else k = next[k];
}
}
int Kmp(char *T,int numt,char *P,int nump,int *next)//T为主串,P为模式串
{
int i=,j=;//i为主串的指针,j为模式串的指针
while(i<=numt-nump)
{
while((T[i]==P[j]&&i<numt)||j==-) ++i,++j;
if(j==nump)//找到匹配串
return i-nump;//返回在主串中的起始位置
j=next[j];
}
return -;//表示无法找到
}
 

Kmp算法浅谈的更多相关文章

  1. Sunday算法浅谈

    一.Sunday算法简介 Sunday算法在我看来比起Kmp和bm都更加容易理解,代码实现也更加简洁.Sunday算法由Daniel M.Sunday在1990年提出,它的思想跟BM算法很相似只不过S ...

  2. [算法]浅谈求n范围以内的质数(素数)

    汗颜,数学符号表达今天才学会呀-_-# 下面是百度百科对质数的定义 质数(prime number)又称素数,有无限个. 质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数. 求质数的方法 ...

  3. Pollard Rho算法浅谈

    Pollard Rho介绍 Pollard Rho算法是Pollard[1]在1975年[2]发明的一种将大整数因数分解的算法 其中Pollard来源于发明者Pollard的姓,Rho则来自内部伪随机 ...

  4. 算法浅谈之DP悬线法

    悬线法 用途 解决给定矩阵中满足条件的最大子矩阵 做法 用一条线(横竖貌似都行)左右移动直到不满足约束条件或者到达边界 定义 \(left[i][j]\):代表从\((i,j)\)能到达的最左位置 \ ...

  5. 浅谈URLEncoder编码算法

    一.为什么要用URLEncoder 客户端在进行网页请求的时候,网址中可能会包含非ASCII码形式的内容,比如中文. 而直接把中文放到网址中请求是不允许的,所以需要用URLEncoder编码地址, 将 ...

  6. 浅谈Hex编码算法

    一.什么是Hex 将每一个字节表示的十六进制表示的内容,用字符串来显示. 二.作用 将不可见的,复杂的字节数组数据,转换为可显示的字符串数据 类似于Base64编码算法 区别:Base64将三个字节转 ...

  7. 浅谈Base64编码算法

    一.什么是编码解码 编码:利用特定的算法,对原始内容进行处理,生成运算后的内容,形成另一种数据的表现形式,可以根据算法,再还原回来,这种操作称之为编码. 解码:利用编码使用的算法的逆运算,对经过编码的 ...

  8. 浅谈大型web系统架构

    动态应用,是相对于网站静态内容而言,是指以c/c++.php.Java.perl..net等服务器端语言开发的网络应用软件,比如论坛.网络相册.交友.BLOG等常见应用.动态应用系统通常与数据库系统. ...

  9. SDUT OJ 数据结构实验之串一:KMP简单应用 && 浅谈对看毛片算法的理解

    数据结构实验之串一:KMP简单应用 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descr ...

随机推荐

  1. python面试的100题(12)

    25.求出列表所有奇数并构造新列表 a=[1,2,3,4,5,6,7,8,9,10] res=[i for i in a if i%2==1] print(res) 结果为:[1, 3, 5, 7, ...

  2. centos7 防火墙的操作

    参考文章:http://blog.csdn.net/Joe68227597/article/details/75207859 http://www.cnblogs.com/cocoat/p/66054 ...

  3. Java类、方法、属性等

    java是面向对象的编程语言 Object,就是指面向对象的对象,对象就是类的具体实例. 在java里,对象是类的一个具体实例.就像:人,指一个类.张三.李四.王五等则是一个个具体的实例,也就是jav ...

  4. 关于按下ctrl+z后,之后的cin失效的问题

    下面这代码按下Ctrl+z结束while输入后,接下来的cin >> val2就无法输入了 #include <iostream> #include <vector> ...

  5. Paper: A novel visibility graph transformation of time series into weighted networks

    1. Convert time series into weighted networks. 2. link prediction is used to evaluate the performanc ...

  6. POJ3258 River Hopscotch(二分最大化最小值)

    题目链接:http://poj.org/problem?id=3258 题意:给n个石头,起点和终点也是两个石头,去掉这石头中的m个,使得石头间距的最小值最大. 思路:二分石头间的最短距离,每次贪心地 ...

  7. JavaScript可视化运行工具推荐

    事件循环.执行栈和任务队列可视化 这个宏任务.微任务,自带例子,也可以自己编辑,不过超过5s的例子就不行 JavaScript Visualizer Tyler Mcginnis大佬的Advanced ...

  8. AcWing 104. 货仓选址

    #include <iostream> #include <algorithm> using namespace std; ; int n; int q[N]; int mai ...

  9. AOP使用

    package com.googosoft.db.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lan ...

  10. calloc函数的使用和对内存free的认识

    #include<stdlib.h> void *calloc(size_t n, size_t size): free(); 目前的理解:  n是多少个这样的size,这样的使用类似有f ...