KMP算法 笔记

KMP算法

简述:该算法是在一个主字符串里找到另一个字符串的非暴力破解算法。

字符串s:abcabcabcd  模式t: abcabcd

暴力破解BF(Brute-Force)算法:每一次都将字符串t沿主字符串一位一位向右硬推,一旦发现有字符对应不同,则将第一个比较位右移一位重新比较。算法复杂度是(m *  n), m、n分别是两个字符串的长度。

Kmp算法:该算法记录了模式t中,的最长前缀,通过这个记录,可以在失配的时候,跳过一些已知的明显不用比较的字符,进行下一步比较。在上面这个例子中我们令两个字符串: char *s = “abcabcabcd”  ;      char *t = “abcabcd”

当依次比较到s[6] = ‘a’  然而t[6] = ‘d’ 时,发现两个字符串失配了,如果在暴力破解算法中,那么就是s[1] = ‘b’  和 t[0] = ‘a’ 开始第二轮比较;但是在kmp算法中, 我们要做的是把

S[6] = ‘a’ 和 t[3]=’a’ 接下去进行比较就可以了 这样就省去了BF算法中 { s[1]&t[0]}、 { s[2]&t[0] } 、{s[3]&t[0] 、{s[4]&t[1]} 、{s[5]&t[2]} , 直接比较s[6]&t[3] ,进而继续比较下去。一旦与主字符串某个字符位失配后,从模式t的第几个字符继续开始匹配的函数就是实效函数next[i] ,其中i表示模式t的第i个位置的字符。

关键点: 其实就是找模式t的i位置之前最长的对称字符前缀

如“abcabcd” 则在’d’字符前的最长前缀是abc所以一旦在’d’位置发生失配, 那就直接去找第四个’a’,再继续匹配。

又如char *t = “abcdabce”如果在’e’处发生失配,那么看e前面的那些字符串,最大对称(可重复)”abc” 长度是3那么接下来由next函数得到的失配后的字符比较位置是t[3] = ‘d’

下面来列举一个可重复的前缀情况 char*t = “abcabcabcd”,如果在’d’出发生失配,那么next函数在t[9] = ‘d’ 出的next失效函数, 通过计算next[9 - 1] = 6 ,之后将t[9] 和 s[startPosition + 6]进行比较


后面是参考网上代码写成的:

在主字符串s 查找字符串t 的位置


#include <iostream>
using namespace std;

 //在主字符串s里找到字符串t的位置
 int KMP_find(const char *s, const char *t){
	 /********************求失效函数***********************/
	 int lenT = strlen(t);
	 int *next = new int[lenT];
	 next[0] = -1;
	 for (int i = 1;i < lenT;i++){
		 int u = next[i - 1];
		 while(t[i] != t[u + 1] && u >= 0)
			 u = next[u]; 
		 if(t[i] == t[u + 1])
			 next[i] = u + 1;
		 else next[i] = -1;
	 }
	 /*****************************************************/
	 int lenS = strlen(s);
	 int i = 0,j = 0;
	 while(i < lenS && j < lenT){
		if(t[j] == s[i]){
			i++;
			j++;
		}
		else if (j == 0)
			i++; //如果t的第0位都无法匹配,那只好主字符串向右移一位
		else
			j = next[j - 1] + 1;
	 }
	 delete next;
	 if(j < lenT)
		 return -1; //匹配失效
	 else
		 return i-j;
 }

 int main(){
	 char *s = "abcabcabcd";
	 char *t = "abcabcd";
	 cout << KMP_find(s,t);
 }



你可能感兴趣的:(算法,delete,破解)