KMP算法

KMP算法要解決的問題就是在字符串(也叫主串)中的模式(pattern)定位問題。說簡單點就是我們平時常說的關鍵字搜索。模式串就是關鍵字(接下來稱它爲T),如果它在一個主串(接下來稱爲S)中出現,就返回它的具體位置,否則返回-1(常用手段)。
假如是在串“SSSSSSSSSSSSSA”中查找“SSSSB”,設置兩個指針i,j,比較到最後一個才知道不匹配,然後其中的i回溯,這個的效率是顯然是最低的。大牛們是無法忍受“暴力破解”這種低效的手段的,於是他們研究出了KMP算法,其思想就如同我們上邊所看到的一樣:“利用已經部分匹配這個有效信息,保持i指針不回溯,通過修改j指針,讓模式串儘量地移動到有效的位置。”所以,整個KMP的重點就在於當某一個字符與主串不匹配時,我們應該知道j指針要移動到哪?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//打印一個數組
void print_array(int *a, int len)
{
	int i;

	for (i = 0; i < len; i++)
	{
		printf("%5d", a[i]);
	}
	printf("\n");
}

int str_index(const char *s, const char *t, int pos)
{
	int i = pos;
	int j = 0;

	while (s[i] != '\0' && t[j]!= '\0')
	{
		if (s[i] == t[j])
		{
			i++;
			j++;
		}else
		{
			i = i - j + 1;
			j = 0;
			//printf("%d\n", i);
		}
	}

	if (t[j] == '\0')
	{
		return i - j;
	}else
	{
		return -1;
	}
}

void get_next(const char *t, int *next, int len)
{
	int j = 0;
	int k = -1;

	next[j] = -1;

	while (t[j] != '\0')
	{
		if (k == -1 || t[j] == t[k])
		{
			next[++j] = ++k;
		}else
		{
			k = next[k];
		}
	}	
}

void get_next2(const char *t, int *next, int len)
{
	int j = 0;
	int k = -1;

	next[j] = -1;

	while (t[j] != '\0')
	{
		if (k == -1 || t[j] == t[k])
		{
			++j;
			++k;
			if (t[j] == t[k])
			{
				next[j] = next[k];
			}else
			{
				next[j] = k;
			}
		}else
		{
			k = next[k];
		}
	}
}


int str_index_kmp(const char *s, const char *t, int pos)
{

	int i = pos;
	int j = 0;
	int len = strlen(t);
	
	int *next = (int *)malloc(sizeof(int) * (len + 1));
	if (next == NULL)
	{
		printf("malloc failed\n");
		exit(1);
	}

	get_next(t, next, len);
	print_array(next, len);

	get_next2(t, next, len);
	print_array(next, len);

	while (s[i] != '\0' && t[j]!= '\0')
	{
		if (s[i] == t[j])
		{
			i++;
			j++;
		}else if (j == 0)
		{
			i++;
		}else
		{
			j = next[j];
			printf("%d\n", i);
		}
	}

	free(next);

	if (t[j] == '\0')
	{
		return i - j;
	}else
	{
		return -1;
	}

}


int main()
{
	int pos;
	char buf[20] = "ABACCCCABABCDHI";
	const char *t = "ABAB";
	pos = str_index(buf, t, 0);
	if (pos  > 0)
	{
		printf("%s\n", buf  + pos);
	}
	
	pos =  str_index_kmp(buf, t, 0);
	if (pos  > 0)
	{
		printf("%s\n", buf  + pos);
	}
	

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