kmp是常用字符串匹配算法,其实现过程为
①算出前缀表(prefix table)。
这里有个技巧,通过对照前一位在前缀表上的值,可以轻松得到需要计算的一位。
首先,第一位初始化为0;
从第二位开始,根据上一位的值计算。
例如 : 计算 ababa 的前缀表,已知 abab 肯定为2。
这时,计算 ababa 只需要比较最后一位的字符 是否和 2 位置的字符相等即可。
相等(很明显相等):则 ababa 的值为 3
若不相等: 则再比较最后一位字符与第一位字符是否相等,等为1,不等为0。
最后将前缀表全部后移一位,第一位初始为-1,方便比较。
代码如下:
for(int i = 1; i < n; i ++ )//计算前缀表
{
if(arr[i] == arr[len])//最后一位与 len位置的相等。 len为前缀表前一位的值。
{
prefix[i] = ++ len;
}
else if(arr[i] == arr[0]) // 不相等则比较第一位。
{
len = 1;
prefix[i] = len;
}
else
{
len = 0;
prefix[i] = len;
}
}
void move_prefix_table(int arr[], int len)//第一位初始化为-1,全部右移一位。
{
for(int i = len - 1; i > 0; i -- )
{
arr[i] = arr[i - 1];
}
arr[0] = -1;
}
②进行比较。
代码如下:
int kmp(char s[], char arr[], int prefix[], int m, int n)
{
for(int i = 0, j = 0; i < m;)
{
if(s[i] == arr[j] && j == n - 1)
{
return i - n + 1;
}
if(s[i] == arr[j])
{
i ++;
j ++;
}
else
{
if(prefix[j] == -1)
{
j = 0;
i ++;
}
else
j = prefix[j];
}
}
return -1;
}
虽然脑袋懂了,但是还是有点讲不清楚。就这样吧自己看懂就行。。。。
实现截图如下: