您的位置:首页 > 其它

KMP算法

2016-04-02 09:53 363 查看

KMP算法实现

<span style="font-size:18px;">/*
函数:KMP算法
时间:2016.04.01
作者:MrZhang
*/
#include<iostream>
#include<string>
#include<cstring>
#include<cassert>
#include<iterator>
using namespace std;
//next数组含义
/*
next[i]:表示从数组[0,i],既是前缀 又是真后缀的最大长度
通俗解释就是又是前缀 又是后缀 并且不等于自己
比如:   a b c a b c a
0 0 0 1 2 3 1
*/
int* GetNext(const string& pattern);
//主串回溯位置公式
/*
i=i+(matched-next[matched])
i:主串下标
matched:子串与主串已经匹配长度
这个公式很重要 忘记了纸上画一下
*/
int KMPMatch(const string& target, const string& pattern);
int* GetNext(const string& pattern)
{
if (pattern.empty())
{
return nullptr;
}
int len = (int)pattern.length();
int* next = new int[len]();
assert(nullptr != next);
int i = 1, k = 0;
next[0] = 0;
while (i < len)
{
k = next[i - 1];
while (0 != k&&pattern[i] != pattern[k])
{
//不相等时 往前找
k = next[k - 1];
}
if (pattern[i] == pattern[k])
{
next[i] =k + 1;//注意这个地方是k+1
}
++i;
}
//这样写后边可以少写一个判断
next[0] = -1;
copy(next, next + len, ostream_iterator<int>(cout, " "));
puts("");
return next;
}

int KMPMatch(const string& target, const string& pattern)
{
if (target.empty() || pattern.empty()
|| pattern.length() > target.length())
{
return -1;
}
//注意next前缀数组至于模式串有关 和主串无关
int *next = GetNext(pattern);
if (nullptr == next)
{
return -1;
}
int i = 0, j = 0;
int lenTar = (int)target.length();
int lenPar = (int)pattern.length();
while (i < lenTar)
{
j = 0;
while (i<lenTar&&j<lenPar&&target[i + j] == pattern[j])
{
++j;
}
if (lenPar == j)
{
return i;
}
//将next[0]设为-1 这里可以不用判断j是否等于0
i = i + (j - next[j]);
}
return -1;
}
int main(void)
{
string pattern = "abccabccabce";
string target = "abccabccabcabcabccabccabce";
cout<<"KMPMatch: "<<KMPMatch(target, pattern)<<endl;
return 0;
}
</span>
有问题或者可以优化的话,欢迎指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: