字符串樸素模式匹配算法的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;
}