标签:
(Partial Match Table)
- 前缀:除了最后一个字符以外,一个字符串的全部头部组合
- 后缀:除了第一个字符以外,一个字符串的全部尾部组合。
- "部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度
因为前四个字符在当前遍历到的位置都是唯一的,所以next值肯定为0。
标黄部分相等,因此next[5]为1
- 标黄部分不相等,因此查找标黄的“D”前面的绿色序列“ABC”的部分匹配字串。
- 查表知道next[6]为3,我们回溯去看长度为3的字序列的部分匹配序列的长度(也就是next[2],值为0)
- 结束,next[5]为0.
- 标黄部分不相等,因此查找标黄的“D”前面的绿色序列“ABCFAB”的部分匹配字串。
- 由next[13]为6去查看next[5]的值(也就是序列“ABCFAB”的部分匹配序列的长度,此处为2)
- 比较T[2] 与T14
- T[2] 与T[14]不相等,继续找出“AB”的部分匹配长度,为零。终止迭代,因此next[14]为0。
#include <iostream>
#include <string>
using namespace std;
void Print(int* array,int length)
{
for(int i = 0;i < length; ++ i)
cout << array[i] << " ";
cout << endl;
}
int CalculateNext(const string& str,int** array)
{
int len = str.size();
int* next = (int *)new int[len];
next[0] = 0;//对于只包含第一个字符的字符序列来说,前缀和后缀都是空集。因此部分匹配长度为0;
int prefix_tail_index = 0;//前缀串中下一次待比较的索引数,因为一开始的时候,都未比较过,索引前缀从零开始
for(int suffix_tail_index = 1;suffix_tail_index < len; ++ suffix_tail_index)
{
while(prefix_tail_index != 0 && str[prefix_tail_index] != str[suffix_tail_index] )
{
//如果前缀的待比较位与后缀最后一位不相等,那么找出长度为suffix_tail_index - 1的字串的最长部分匹配字串
// 从该串的后面一位开始与str[suffix_tail_index]
prefix_tail_index = next[prefix_tail_index - 1];
}
if(str[prefix_tail_index] == str[suffix_tail_index])
{
//在求出了next[i - 1]的基础上发现最长部分匹配序列可以向后扩展一位。
prefix_tail_index ++;
//记录最长部分匹配长度为prefix_tail_index,但是前缀串的最后一个字符的索引为prefix_tail_index - 1;
next[suffix_tail_index] = prefix_tail_index;
continue;
}
else
{
next[suffix_tail_index] = 0;
}
}
*array = next;
return len;
}
int KMP(const string& o_str,const string& target)
{
int *pmt;
int tlen = CalculateNext(target,&pmt);
int match_bits = 0;//比较过程两个序列前面已经相同的位数
int start_pos = 0;//某次比较过程中,原串的起始比较位置
int olen = o_str.size();
while(match_bits < tlen && start_pos + match_bits < olen)
{
if(target[match_bits] == o_str[start_pos + match_bits])
{
match_bits ++;
cout << "match_bits:" << match_bits << endl;
}
else
{
if(match_bits == 0)
{
//前面没有发现匹配的字符
start_pos += 1;
}
else
{
//移动位数 = 已匹配的字符数 - 对应的部分匹配值
int offset = match_bits - pmt[match_bits - 1];
start_pos += offset;
match_bits = pmt[match_bits - 1];
}
cout << "start_pos:" << start_pos << ",match_bits:" << match_bits << endl;
}
}
if(match_bits == tlen)
return start_pos;
else
return -1;
}
int main()
{
// string str1("ABCDABD");
string str1("ABCFABCDABCFABD");
// string str2("ABD");
string str2("ABCFABD");
cout << KMP(str1,str2) << endl;
return 0;
}
标签:
原文地址:http://www.cnblogs.com/rainySue/p/KMP-suan-fa.html