模式匹配KMP

字符串樸素模式匹配算法的2種實現:

//1.樸素的模式匹配算法,用while實現

int StrStr_While(const char* pStr, const char* pSub, int* pos)
{
	int nRet = 0;
	int pStrLen = strlen(pStr);
	int pSubLen = strlen(pSub);
	int i = 0, j = 0;
	int nLen = pStrLen - pSubLen;

	if (pStr == NULL || pSub == NULL)
	{
		nRet = -1;
		printf("param input error!");
		return nRet;
	}

	while (i < pStrLen && j < pSubLen)
	{
		if (*(pStr + i) == *(pSub + j))
		{
			++i;
			++j;
		}
		else
		{
			i = i - j + 1;
			j = 0;
		}
	}

	if (j == pSubLen)
		*pos = i - j + 1;

	return nRet;
}


 

//2.樸素的模式匹配,用for循環實現

int StrStr_For(const char* pStr, const char* pSub, int* pos)
{
	int nRet = 0;
	int pStrLen = strlen(pStr);
	int pSubLen = strlen(pSub);
	int i = 0, j = 0;
	int nLen = pStrLen - pSubLen;

	if (pStr == NULL || pSub == NULL)
	{
		nRet = -1;
		printf("param input error!");
		return nRet;
	}

	for (i = 0; i <= nLen; ++i)
	{
		for (j = 0; j < pSubLen; ++j)
		{
			if (*(pStr + i + j) != *(pSub + j))
				break;
		}

		if (j == pSubLen)
		{
			*pos = i + 1;
			break;
		}
	}
	
	return nRet;
}


 

實現字符串的匹配有高效的算法,那就是KMP算法,實現如下:

//取得KMP算法需要用的的next數組

int GetNext(const char* pStr, int nNext[])
{
	int nRet = 0;
	if (pStr == NULL || nNext == NULL)
	{
		nRet = -1;
		printf("param input error!\n");
		return nRet;
	}

	int nLen = strlen(pStr);
	int i = 0, j = -1;
	nNext[i] = j;
	while (i < nLen - 1)
	{
		if (j == -1 || pStr[i] == pStr[j])
		{
			++i;
			++j;
			nNext[i] = j;
		}
		else
		{
			j = nNext[j];
		}
	}

	return nRet;
}



//取next數組的改進型算法!剔除多個重複字符的next數組值持續增長!

int GetNextVal(const char* pStr, int nNext[])

{

	int nRet = 0;

	if (pStr == NULL || nNext == NULL)

	{

		nRet = -1;

		printf("param input error!\n");

		return nRet;

	}



	int nLen = strlen(pStr);

	int i = 0, j = -1;

	nNext[i] = j;

	while (i < nLen - 1)

	{

		if (j == -1 || pStr[i] == pStr[j])

		{

			++i;

			++j;

			if (pStr[i] != pStr[j])

				nNext[i] = j;

			else

				nNext[i] = nNext[j];

		}

		else

		{

			j = nNext[j];

		}

	}



	return nRet;

}



 

這是針對類似aaaaaaab這樣的字符串使用上面兩個函數取得的next數組值得比較。注意書上的都是字符串從數組的下標爲1的位置開始存儲的。我改進的算法是還是讓字符串從數組下標爲0的位置開始存儲。所以上面的next數組值都要相較與原來的值減1。

 

//調用上面的函數實現KMP高效字符串模式匹配算法!


int Index_KMP(const char* pStr, const char* pSub, int* nPos)
{
	int nRet = 0;
	if (pStr == NULL || pSub == NULL || nPos == NULL)
	{
		nRet = -1;
		printf("param input error!\n");
		return nRet;
	}

	int pStrlen = strlen(pStr);
	int pSublen = strlen(pSub);

	int nNext[255] = { 0 };
	//nRet = GetNext(pSub,nNext);
	nRet = GetNextVal(pSub, nNext);
	if (nRet != 0)
	{
		printf("call GetNext() func is error!\n");
		return nRet;
	}

	int i = 0, j = 0;
	while (i < pStrlen && j < pSublen)
	{
		if (j == -1 || *(pStr + i) == *(pSub + j))
		{
			++i;
			++j;
		}
		else
		{
			j = nNext[j];
		}
	}

	if (j == pSublen)
		*nPos = i - j + 1;

	return nRet;
}


 

 

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