朴素的字符串匹配算法
这是最容易理解的字符串匹配算法,我们用两个指针ai,bi分别指待匹配串a和模式串b的起始位置,当a[ai]==b[bi]时ai++,bi++,一旦失配,ai=ai-bi+1(原来位置的后一位),bi=0;
显然这种方法不断重复访问模式串的前部分使得匹配速度变慢
例如
a串:aaaaaaaaaaaaaaaaab
b串:aaaaaaaaaab
每次匹配时我都要将b串访问一遍,原因在于每次匹配失败我都将bi回到0;
对于这里的改进就要引入next数组来记录一个合适的位置使得bi不用每次都回到0
next数组
int next[b.size()];
for(int i=1;i<b.size();i++) next[i]=0;
next[0]=-1;
next[1]=0;
for(int i=2;i<b.size();i++)
{
int k=next[i-1];
if(b[k]==b[i-1]) next[i]=k+1;
else
{
while(k!=-1)
{
k=next[k];
if(b[k]==b[i-1]) break;
}
next[i]=k+1;
}
}
这里是kmp算法最重要的部分
- next数组的作用是当第i位的字符失配的时候bi回到next[bi]的位置
- next[i]的实际意义是 i位置以前的next[i]个字符(不包括 i ) 和从0开始的前 i 个字符(也即是 next[i]位置以前的next[i]个字符(不包括next[i]))相等。因此我们可以得出b [ i ]==b [ next [ i ] ] 时next [ i+1 ] = next [ i ]+1
- 同上i,next[i]和next[next[i]]的前next[next[i]]个字符相等,当不满足2时,如果b[next[next[i]]==b[i],那么next[i+1]=next[next[i]]+1,同理我可以一直递归下去知道next的值等于0;
匹配
for(int i=0,j=0;i<a.size();)
{
if(a[i] == b[j])
{
i++;
j++;
}
else
{
if(j==-1)
{
i++;
j++;
}
else j=next[j];
}
if(j==b.size()) return true;
}
return false;
当a[ai] == b[bi] 时正常匹配,当失配时让bi回到next[bi],继续匹配a[ai]和b[bi],直到next[bi] == -1,表示已经找完了,都没发现可以匹配的,所以ai++,bi++;
小结
我们可以看出next数组和匹配的代码部分很相似,实际上,求next数组时模式串自我匹配的过程。
来源:https://blog.csdn.net/weixin_42844091/article/details/100777055