KMP算法
Posted cccv
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KMP算法相关的知识,希望对你有一定的参考价值。
1 void Solution::KMPSearch(string pat, string txt) 2 { 3 int M = pat.length(); 4 int N = txt.length(); 5 int lps[M]; // 记录最长的相同的前缀后缀的长度 6 computeLPSArray(pat, lps); 7 8 int i = 0; 9 int j = 0; 10 while(i < N) 11 { 12 if(pat[j] == txt[i]) 13 { 14 i++; 15 j++; 16 } 17 if(j == M) 18 { 19 cout << "Found pattern at index " << i-j << endl; 20 j = lps[j-1]; 21 } else if(i < N && pat[j] != txt[i]) 22 { 23 if(j != 0) 24 j = lps[j-1]; 25 else 26 i++; 27 } 28 } 29 30 } 31 32 33 void Solution::computeLPSArray(string pat, int* lps) 34 { 35 int M = pat.length(); 36 int i = 1; 37 int len = 0; 38 lps[0] = 0; 39 40 while(i < M) 41 { 42 if(pat[i] == pat[len]) 43 { 44 len++; 45 lps[i] = len; 46 i++; 47 } 48 else 49 { 50 if(len != 0) 51 { 52 len = lps[len-1]; 53 } 54 else 55 { 56 lps[i] = 0; 57 i++; 58 } 59 } 60 } 61 }
假设你对KMP算法有了解但感到困惑,本文不解释KMP算法的定义。
详细说一下KMP算法,刚看到的时候一头雾水,想不明白lps[]这个数组的作用。
在说明lps[]之前先说明一下最长的相同的前缀后缀的意思
比如字符串:"ababab"
前缀:"ababa", "abab", "aba" ,"ab", "a", "",
后缀:"babab", "abab", "bab", "ab", "b", "",
可以观察到最长的相同的前缀后缀在这里为"abab",长度为4
lps[]的作用就是记录字符串的最长的相同的前缀后缀的长度,这里长度为4,所以lps[5] = 4,
数组下标为5是因为字符串"ababab"的最后一个字符"b"的下标为5.(这里先不考虑lps[]是怎么实现的,明白它代表的意思就行了,后面会说明怎么实现的)
当我们知道最长的相同的前缀和后缀的长度,我们能用它来干什么呢?
“abab" 的最长的相同的前缀后缀为"ab",长度为2
所以"abab"的前2位 和 后2位相同
前缀: (ab) ab
后缀:ab (ab)
假如当我们匹配两个字符串
pat = "abab" , txt = "ababab"
当第一次完全匹配时
a b a b a b
a b a b
此时i = 4, j = 4,根据算法此时打印找到的第一个下标,然后让j = lps[j-1] >> j = lps[3]
lps[3]保存的是"abab"的最长的相同的前缀后缀的长度,这里为”ab",所以长度为2,所以 j = 2;
因为在txt”ababab"找到的第一个字符串"abab"包含了要找的字符串"abab"的后两位“ab”,
而我们要找的字符串“abab”的前两位是"ab",所以我们可以直接跳过前两位,而从第三位字符"a"开始对比
因为"ab"长度为2,所以它的下一位的下标j应该为2,所以下一次循环为 if(pat[j] == txt[i]) >> if(pat[2] == txt[4]);
txt:a b (a b) a b
pat: (a b) a b
pat index 0 1 2 3
以上是关于KMP算法的主要内容,如果未能解决你的问题,请参考以下文章