数据结构与算法3:KMP
KMP算法是一个经典的字符串匹配的高效算法,虽然实际不常用。
KMP是对朴素算法的改进。它的思路的关键在于,当发生失配的情况的时候,我们不一定只往后移动一位。由于我们已经匹配了一部分,那么我们就可以根据已匹配的那一部分模式的特点,来确定往后移动多少位。
具体来说,比如ababs,模式abas,发现第四位不匹配,那么就需要往后移动2位,避免不可能的匹配情况,同时也不能遗漏可能的情况。KMP的这种过程需要预先对模式进行处理,得到一个部分匹配表。
下面是C语言代码。
#include <stdio.h>
#include <string.h>
#define N 100
int table[N];
char text[N];
char m[N];
int lenT;
int lenM;
int cmp(int a, int b, int len)
{
int i;
for (i = 0; i < len; i++)
{
if (m[a+i] != m[b+i])
{
//printf("diff: %d %d %d\n",a,b,len);
return 0;
}
}
//printf("same: %d %d %d\n",a,b,len);
return 1;
}
void initTable()
{
int i,j;
lenT = strlen(text);
lenM = strlen(m);
table[0] = 0;
for (i = 0; i < lenM; i++)
{
//printf("i=%d\n", i);
for (j = i; j >= 0; j--)
{
if (cmp(0, i-j+1, j))
{
table[i] = j;
break;
}
//m[0],m[j] m[i-j],m[i]
}
}
for (i = 0; i < lenM; i++)
printf("%d", table[i]);
}
int kmp()
{
int i=0, j=0;
while(i < lenM && j < lenT)
{
if (m[i] == text[j])
{
if (i == lenM-1)
return j-i;
i++;
j++;
}
else
{
if (i > 0)
i = table[i-1];
else
j++;
}
}
return -1;
}
int main()
{
scanf("%s", text);
scanf("%s", m);
initTable();
printf("%d", kmp());
return 0;
}