KMP算法初步理解
@TOCKMP算法
KMP算法解决问题
穷举法的介绍
KMP算法介绍
一、KMP算法是解决串与子串匹配问题的算法,因为穷举法对于重复性较多的串的匹配(如‘00000000001’与‘00001’的匹配)重复性匹配次数过多,效率低,时间复杂度为O(n*m),因此改进算法即为KMP算法,时间复杂度为O(n+m)。
二、穷举法的介绍
穷举法就是从串的第一位开始匹配,当第一位匹配后匹配下一位,不匹配则回溯,到下一位重新匹配。
int main(String a,String b) {
int n = a.length; //串的长度
int m = b.length;
int p,k = 0; //p为串a当前匹配位,k为子串b当前匹配的位
while(k < m && p <= n-m) {
if( a[p] == b[k] ) {
p++;
k++;
}
else{
p = p - k + 1; //回溯
k = 0;
}
}
if( p <= n-m ) return p;
else return -1;
}
三、KMP算法介绍
1、串的前缀和后缀
前缀:从第1位开始到第n位结束(n不能为串的长度)
后缀:从第-1位开始到第-n位结束
eg:‘watermelon’
前缀:‘w’,‘wa’,‘wat’…‘watermelo’
后缀:‘n’,‘on’,…‘atermelon’
当串中前缀和后缀有重复部分时,串和子串的匹配可以无需从下一位开始,直接跳转到重复部分。
如:
‘ababd’
‘abd’
此时匹配的串为aba,前缀和后缀有重复部分a,因此子串可直接从a部分开始匹配。
跳转长度 = 匹配长度 - 重复长度
注意,此时重复长度应为最长重复子串长度
2、KMP算法思路
KMP算法就是利用上述串的前后缀重复,无需按步重复性匹配,从而减少了时间复杂度。因此,KMP算法的核心为求串的最长重复子串长度k。用数组s[j]表示。
求取s[j]时,已知s[j-1]=k,当a[j]=a[k]时,易得s[j]=s[j-1]+1;
当a[j] != a[k]时,求取的最长重复子串长度必定小于k,如图可知,求取s[j]即求一个串的结尾为a[j]的s,因此可利用递归的思路,令k=s[k]。
图源网络,主要用于学习总结
void Getnext(int s[],String a)
{
int j=0,k=-1;
s[0]=-1;
while(j<a.length-1)
{
if(k == -1 || a[j] == a[k])
{
j++;k++;
s[j] = k;
}
else k = s[k];
}
}