KMP算法-找出字串出现的第一个位置
我们先得出子串(也就是标准串的NEXT[]表的值。上讲已经讲过如何算出给定子串的NEXT[]表的值,此讲不再冗述。
第一步给出算NEXT[]表值的算法
arr[]为题目给出的标准串,brr[]是给定要寻找位置的子串。
next[]是我们新开辟的数组为空,等待我们算出值放入。
void GETNEXT(char brr[], char next[])
{
int j=0, k=-1;
next[0] = -1;
while(j < strlen(brr)-1)
{
if(brr[j]==brr[k] || k==-1)
{
j++;
k++;
next[j] = k;
}
else k = next[k];
}
}
第二步开始找
先给出代码
arr[]为题目给出的标准串,brr[]是给定要寻找位置的子串。
next[]是我们新开辟的数组为空,等待我们算出值放入。
char next[];
int KMPIndex(char arr[], char brr[])
{
GETNEXT(brr, next);
int i=0, j=0;
while(i < strlen(arr) && j < strlen(brr) //当标准串没有扫完,并且模式串也没有扫完
{
if(j==-1 || arr[i)==brr[j])
{
i++;
j++;
}
else j = next[j];
}
//两方若有一方先扫完,或都扫完
if(j >= strlen(brr)//匹配成功
return i-strlen(brr);
else return -1;
}
给大家举个栗子
给定标准串 a a a a b
给定模式串 a a a b
显然模式串的NEXT[]表的值为
j | 0 | 1 | 2 | 3 |
---|---|---|---|---|
brr [ ] | a | a | a | b |
next [ ] | -1 | 0 | 1 | 2 |
i=0, j=0时
‘a’ = ‘a’
arr[0] == brr[0] ,所以i++, j++
i=1, j=1时
‘a’ = ‘a’
arr[1] == brr[1] , 所以i++, j++
i=2, j=2时
‘a’ = ‘a’
arr[2] == brr[2] , 所以i++, j++
i=3, j=3时
‘a’ != ‘b’
所以 j=next[j]=next[3]=2; i不变
i=3, j=2时
‘a’ = ‘a’
arr[3] == brr[2] , 所以i++, j++
i=4, j=3时
‘b’ = ‘b’
arr[4] == brr[3] , 所以i++, j++
因为i >= strlen(arr),循环结束
并且j >= strlen(brr) 说明找到啦
返回子串第一次出现的位置 i-strlen(brr)
就是现在 i 代表的位置是标准串中‘b’的位置,我们减去子串的长度,就是子串第一次出现的位置