1.算法解决问题描述
字符串匹配问题,即在长的字符串序列中去匹配短的字符串。
2.算法解析
简单的字符串匹配是通过对匹配字符串平移一位,进行逐个比较。这样的话算法复杂度达到o(n*m).
KMP算法是首先得出匹配字符串的特征,这样当两个不匹配时,不用只是平移一位了。极大的减少
复杂度。它可以达到o(n+m)。
KMP算法主要的是求覆盖函数(overlay_function)-——匹配字符串本身的特征。
比如字符串:abaabcaba
子串 | 值 |
a | -1 |
ab | -1 |
aba | 0 |
abaa | 0 |
abaab | 1 |
abaabc | -1 |
abaabca | 0 |
abaabcab | 1 |
abaabcaba | 2 |
-1表示没有覆盖。
假如覆盖函数的值为k,则满足:a0a1...ak=aj-k...aj
可以采用递归的方法求覆盖函数。对pattern的前j+1序列字符,则有以下可能:
(1) patter[k+1]==pattern[j+1] 此时overlay(j+1)=k+1=overlay(j)+1;
(2)pattern[k+1]!=pattern[j+1] 此时只能在pattern的前k+1个子字符中找,h=overlay(k),如果pattern[h+1] == pattern[j+1]
则overlay(j+1)=h+1;否则重复(2)过程。
<span style="font-size:14px;">void compute_overlay(const string& pattern)
{
const int pattern_length = pattern.size();
int *overlay_function = new int[pattern_length];
int index;
overlay_function[0] = -1;
for(int i=1;i<pattern_length;++i)
{
index = overlay_function[i-1];
while(index>=0 && pattern[i]!=pattern[index+1])
{
index = overlay_function[index];
}
if(pattern[i]==pattern[index+1])
{
overlay_function[i] = index + 1;
}
else
{
overlay_function[i] = -1;
}
}
for(i=0;i<pattern_length;++i)
{
cout<<overlay_function[i]<<endl;
}
delete[] overlay_function;
}</span>
KMP算法是:当发生在j长度不匹配时,只要把pattern向右移动 j-overlay(j) 长度就可以了。
<span style="font-size:14px;">int kmp_find(const string& target,const string& patter)
{
const int target_length = target.size();
const int pattern_length = pattern.size();
int * overlay_value = new int[pattern_length];
overlay_value[0] = -1;
int index = 0;
for(int i=1;i<pattern_length;++i)
{
index = overlay_value[i-1];
while(index>=0 && pattern[index+1]!=pattern[i])
{
index = overlay_value[index];
}
if(pattern[index+1]==pattern[i])
{
overlay_value[i] = index +1;
}
else
{
overlay_value[i] = -1;
}
}
//match algorithm start
int pattern_index = 0;
int target_index = 0;
while(pattern_index<pattern_length&&target_index<target_length)
{
if(target[target_index]==pattern[pattern_index])
{
++target_index;
++pattern_index;
}
else if(pattern_index==0)
{
++target_index;
}
else
{
pattern_index = overlay_value[pattern_index-1]+1;
}
}
if(pattern_index==pattern_length)
{
return target_index-pattern_index;
}
else
{
return -1;
}
delete [] overlay_value;
}</span>