KMP算法

一、KMP算法思想:定義兩個整形變量 i、j,i 在源串的起始位置,j 在子串的起始位置,然後i、j同時開始向後走,如果i、j對應的值匹配就都++,如果不匹配,則 i 不動,j回退到k位置,這個k是存在next數組裏的值,稍後說next數組

二、舉例計算:

                            

(1)我們知道 1 和 2 相等,1 和 3 相等,則可以推斷得到 2 和 3 相等,所以就有P0...Pk-1 = Px...Pj-1 (x是未知數)

       即有 P0...Px-1 = Pj-k...Pj-1

      在P串中存在兩個相等的最大真子串,真子串的限制:

                                                                                          第一個串以0下標開始

                                                                                          第二個串以 j - 1結束      K的值應該是真子串的長度

(2)next數組:

          next數組的長度:strlen(p); 與子串長度相等

          next[0] = -1;  next[1] = 0;

舉例:求出下面串的next數組

P a b a b c a b c d a b c d e
next -1 0 0 1 2 0 1 2 0 0 1 2 0 0

nextvalue數組:結合它的next數組求,比如下標爲3的字符a,它的next值爲0,而它的next[0] 也等於a,所以這個a的nextvalue值就取0下標a的next值,即爲-1,如果不相等那麼它的nextvalue值就等於它的next值。 

P a b c a a b b c a b c a a b
next -1 0 0 0 1 1 2 0 0 1 2 3 4 5
nextvalue -1 0 0 -1 1 0 2 0 -1 0 0 -1 1 0

 代碼展示:

void GetNext(int *next, const char *der)
{
	int lender = strlen(der);
	next[0] = -1;
	next[1] = 0;
	int i = 2;
	int k = 0;
	while(i < lender)
	{
		if((k == -1) || der[k] == der[i-1])
		{
			next[i++] = ++k; //next[i] = k+1; i++; k+=1;
		}
		else
		{
			k = next[k];
		}
	}
}
int KMP(const char *src, const char *der,int pos)
{
	int i = pos;
	int j = 0;
	int lensrc = strlen(src);
	int lender = strlen(der);
	int *next = (int *)malloc(lender*sizeof(int));  //跟子串的長度相等
	assert(next != NULL);

	GetNext(next,der);

	while(i<lensrc && j<lender)
	{
		if((j == -1)|| src[i] == der[j])
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];
		}
	}
	free(next);
	if(j >= lender)
	{
		return i-j;
	}
	else
	{
		return -1;
	}
}
int main()
{
	char *s = "ababcabcdabcde";
	char *sub = "abcd";
	printf("%d\n",KMP(s,sub,10));
	return 0;
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章