The key of Kmp is to build a look up table that records the match result of prefix and postfix. Value in the table means the max len of matching substring that exists in both prefix and postfix. In the prefix this substring should start from 0, while in the postfix this substring should ends at current index.

For example, now we have a string "ababc"

The KMP table will look liks this:

 a  b  a  b  c
-1 0 1 2

(Note: we will not match substring with itself, so we will skip index 0)

So how does this table help us search string match faster?

Well, the answer is if we are trying to match a char after posfix with target string and failed, then we can smartly shift the string, so that the matching string in perfix will replace postfix and now we can try to match the char after prefix with this char in target.

Take above string as an example.

Now we try to match string "ababc" with "abababc".

We will initially have match as below

 0 1 2 3 4 5 6
 a b a b a b c (string x)
a b a b c (string y)
-1 0 1 2

We found char at index 4 does not match, then we can use look up table and shift the string y wisely.

We found table[3] = 2, which means we can shift the string y rightward by 2, and still have same but shorter prefix before index 4, like this:

 0 1 2 3 4 5 6
a b a b a b c (string x)
a b a b c (string y)
-1 0 1 2

If there is a long gap between prefix and postfix, this shift can help us save a lot of time. In the brute force way, we cannot do that because we have no information of the string. We have to compare each possible pair of chars. While in KMP, we know the information of string y so we can move smartly. We can directly jump to the next possible match pairwhile discard useless pair of chars.

We are almost done with KMP, but we still have one special case that needs to be taken care of.

Say now we have a input like this:

 0 1 2 3 4 5
a a b a a a
-1 1 0 2 3

How should we build the KMP table for this string?

Say the pointer in prefix is 'x', which is at index 2 now and the pointer in postfix is 'y' which is at index 5 now. We need to match 'b' pointed by x with 'a' pointed by y. It is an unmatched pair, how should we update the cell?

Well, we really don't need to reset it to 0, that will make us skip a valid shorter matching substring "aa".

What we do now is just to shorten the length of substring by 1 unit and try to match a shorter substring "aa". This can be done by moving pointer x to the index recorded in [indexOf(x) - 1] while keep pointer y stay still. This is because by following the value in KMP table we can always make sure previous part of prefix and postfix is matched even we have shorten their length, so wo only need to care about the char after matched part in prefix and posfix.

Code: [Java]

// JAVA program for implementation of KMP pattern
// searching algorithm class KMP_String_Matching {
void KMPSearch(String pat, String txt)
{
int M = pat.length();
int N = txt.length(); // create lps[] that will hold the longest
// prefix suffix values for pattern
int lps[] = new int[M];
int j = 0; // index for pat[] // Preprocess the pattern (calculate lps[]
// array)
computeLPSArray(pat, M, lps); int i = 0; // index for txt[]
while (i < N) {
if (pat.charAt(j) == txt.charAt(i)) {
j++;
i++;
}
if (j == M) {
System.out.println("Found pattern "
+ "at index " + (i - j));
j = lps[j - 1];
} // mismatch after j matches
else if (i < N && pat.charAt(j) != txt.charAt(i)) {
// Do not match lps[0..lps[j-1]] characters,
// they will match anyway
if (j != 0)
j = lps[j - 1];
else
i = i + 1;
}
}
} void computeLPSArray(String pat, int M, int lps[])
{
// length of the previous longest prefix suffix
int len = 0;
int i = 1;
lps[0] = 0; // lps[0] is always 0 // the loop calculates lps[i] for i = 1 to M-1
while (i < M) {
if (pat.charAt(i) == pat.charAt(len)) {
len++;
lps[i] = len;
i++;
}
else // (pat[i] != pat[len])
{
// This is tricky. Consider the example.
// AAACAAAA and i = 7. The idea is similar
// to search step.
if (len != 0) {
len = lps[len - 1]; // Also, note that we do not increment
// i here
}
else // if (len == 0)
{
lps[i] = len;
i++;
}
}
}
} // Driver program to test above function
public static void main(String args[])
{
String txt = "ABABDABACDABABCABAB";
String pat = "ABABCABAB";
new KMP_String_Matching().KMPSearch(pat, txt);
}
}
// This code has been contributed by Amit Khandelwal.

  

Reference:

https://www.geeksforgeeks.org/java-program-for-kmp-algorithm-for-pattern-searching-2/

https://leetcode.com/problems/shortest-palindrome/discuss/60113/Clean-KMP-solution-with-super-detailed-explanation

KMP Demo的更多相关文章

  1. KMP算法实现

    链接:http://blog.csdn.net/joylnwang/article/details/6778316 KMP算法是一种很经典的字符串匹配算法,链接中的讲解已经是很明确得了,自己按照其讲解 ...

  2. kmp算法,求重复字符串

    public class Demo { public static void main(String[] args) { String s1 = "ADBCFHABESCACDABCDABC ...

  3. KMP 算法 & 字符串查找算法

    KMP算法 Knuth–Morris–Pratt algorithm 克努斯-莫里斯-普拉特 算法 algorithm kmp_search: input: an array of character ...

  4. 【数据结构&算法】10-串基础&KMP算法源码

    目录 前言 串的定义 串的比较 串的抽象类型数据 串与线性表的比较 串的数据 串的存储结构 串的顺序存储结构 串的链式存储结构 朴素的模式匹配算法 模式匹配的定义 朴素的匹配方法(BRUTE FORC ...

  5. 通过一个demo了解Redux

    TodoList小demo 效果展示 项目地址 (单向)数据流 数据流是我们的行为与响应的抽象:使用数据流能帮我们明确了行为对应的响应,这和react的状态可预测的思想是不谋而合的. 常见的数据流框架 ...

  6. KMP算法求解

    // KMP.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using namespac ...

  7. 很多人很想知道怎么扫一扫二维码就能打开网站,就能添加联系人,就能链接wifi,今天说下这些格式,明天做个demo

    有些功能部分手机不能使用,网站,通讯录,wifi基本上每个手机都可以使用. 在看之前你可以扫一扫下面几个二维码先看看效果: 1.二维码生成 网址 (URL) 包含网址的 二维码生成 是大家平时最常接触 ...

  8. 在线浏览PDF之PDF.JS (附demo)

    平台之大势何人能挡? 带着你的Net飞奔吧!:http://www.cnblogs.com/dunitian/p/4822808.html#skill 下载地址:http://mozilla.gith ...

  9. 简单有效的kmp算法

    以前看过kmp算法,当时接触后总感觉好深奥啊,抱着数据结构的数啃了一中午,最终才大致看懂,后来提起kmp也只剩下“奥,它是做模式匹配的”这点干货.最近有空,翻出来算法导论看看,原来就是这么简单(先不说 ...

随机推荐

  1. 第三章 RNA测序

    第三章 RNA测序   RNA测序(RNA Sequencing,简称RNA-Seq,也被称为全转录物组鸟枪法测序Whole Transcriptome Shotgun Sequencing,简称WT ...

  2. jQuery 操作 html5 data-* 属性

    Html 部分: <a class="nav-item" href="javascript: void(0)" data-id="{{$item ...

  3. centos7 编译安装mysql

    centos 7 安装mySql   1,准备mySql源码安装 #wget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.23.tar ...

  4. bitnami redmine svn配置

    采用bitnami 方案安装redmine svn服务器端会自己进行安装 1.创建版本库 首先进入remine安装目录的subversion/bin目录,例如我的安装目录是“/opt/redmine/ ...

  5. MYSQL 问题小总结

    mysql 问题小总结 1.MySQL远程连接ERROR 2003(HY000):Can't connect to MySQL server on ‘ip’(111)的问题 通常是mysql配置文件中 ...

  6. c++中类的静态数据成员

    有时需要为某个类的所有对象分配一个单一的存储空间,这个存储空间只是被这个类的对象访问,其他人不能访问,那么这时静态的成员变量是有用的.例如下面用来统计一共创建了多少个对象的变量num class cl ...

  7. 2018.10.23 NOIP模拟 “新”的家园(缩图+dijksta/spfa)

    传送门 考试70分骗分写挂了=30分=全场最低. 哎今天230垫底了. 这题出的挺好. 对于非关键点直接缩点. 每次把要查的insertinsertinsert进缩好的图里面跑spfa/dijkstr ...

  8. 2018.09.21 codeforces1051D. Bicolorings(线性dp)

    传送门 sb线性DP. f[i][j][0/1/2/3]f[i][j][0/1/2/3]f[i][j][0/1/2/3]表示前i列j个连通块且第i列状态为00/01/10/11时的方案总数. 这个显然 ...

  9. 2018.09.06 警卫安排(树形dp)

    描述 太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫. 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状:有边直接相连的宫殿可以互相望见.大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全 ...

  10. HDU 1513 && POJ 1159 Palindrome (DP+LCS+滚动数组)

    题意:给定一个字符串,让你把它变成回文串,求添加最少的字符数. 析:动态规划是很明显的,就是没有了现思路,还是问的别人才知道,哦,原来要么写,既然是回文串, 那么最后正反都得是一样的,所以我们就正反求 ...