标签:kmp
Kmp算法我是看July博客学习,这里只是做个笔记,详细内容见July的blog: http://blog.csdn.net/v_july_v/article/details/7041827
Kmp算法的用途:有一个文本串S和一个模式串P,现在要查找P在S中的位置。暴力匹配算法需要对文本串S进行回溯,kmp算法就是让文本串不回退,只需要移动模式串j即可。
Kmp算法大体思想:就是当s[i]==p[j]时,我们对i++,j++;如果不相等则令j=next[j]。这里next[j]为j字符之前的字符串中有多大长度的相同前缀后缀。相当于将模式串向右移动了j=next[j]位。Next数组的求解采用的是迭代的思想,需要分p[j]是否等于p[k]两种情况以求得next[j+1]。
时间复杂度:暴力匹配算法的时间复杂度为O(n*m)(最差的情况). Kmp算法的时间复杂度为O(n+m)。这里n和m分别为文本串和字符串的长度。
优化next数组:next数组主要针对模式串abab的情况,比如在文本串abacab中寻找,此时当p[3]与s[3]匹配失败时,则将abab向右移动两位,此时p[1]仍然等于b,匹配必然失败,优化的next数组主要解决这个问题。当p[3]=p[next[3]]时 令next[3]=next[next[3]]。看代码则很好理解了。
以上则是个人理解笔记,下面给出具体代码:
1:kmp算法代码
#include <iostream>
using namespace std;
// 获取next数组
void getNext(int *next, const char *p) // 已知next[j] 求next[j+1] 分p[j]是否等于p[k]两种情况 迭代的思想
{
next[0] = -1;
int k = -1;
int j = 0;
while(j < strlen(p)-1)
{
if(k == -1 || p[j] == p[k])
{
k++;
j++;
next[j] = k;
}
else{
k = next[k]; // 继续迭代
}
}
}
// 获取优化next数组
void getNextOpt(int *next, const char *p) // 已知next[j] 求next[j+1] 分p[j]是否等于p[k]两种情况 迭代的思想
{
next[0] = -1;
int k = -1;
int j = 0;
while(j < strlen(p)-1)
{
if(k == -1 || p[j] == p[k])
{
k++;
j++;
if(p[j] != p[k]) // 对next数组进行优化 以对abab 这样的不需要进行重复
next[j] = k;
else next[j] = next[k];
}
else{
k = next[k]; //
}
}
}
// kmp 算法
int kmpSearch(const char *p, const char*s)
{
int ptrLen = strlen(p); // 获取模式串和文本串的长度
int strLen = strlen(s);
int *next = new int[ptrLen]; // 动态申请next数组
getNext(next, p); // 获取next数组
int i = 0, j = 0;
while(i < strLen && j < ptrLen){
if(j == -1 || s[i] == p[j])
{
i++;
j++;
}
else if(j == 0) // 这样对于首字符不满足的时候直接优化
i++;
else{
j = next[j];
}
}
delete[] next; // 释放动态申请的数组
if(j == ptrLen)
return i - j;
else return -1;
}
int main(){
char *ptr = "abcd";
char *str = "abababcd";
cout << kmpSearch(ptr, str) << endl;
return 0;
}
2:暴力匹配算法
#include <iostream>
using namespace std;
int violenceSearch(const char *p, const char *s)
{
int ptrLen = strlen(p); // 获取模式串和文本串的长度
int strLen = strlen(s);
int i = 0, j = 0;
while(i < strLen && j < ptrLen){
if(s[i] == p[j])
{
i++;
j++;
}
else{
i = i-j+1;
j = 0;
}
}
if(j == ptrLen)
return i - j;
else return -1;
}
int main(){
char ptr[100];
char str[100];
cin >> ptr >> str;
cout << violenceSearch(ptr, str) << endl;
}
3:求最大长度表算法
// 针对一个字符串获得最大长度的相同前缀后缀
int getMaxFix(const char *p, int pLen)
{
int k =pLen/2;
while(k > 0)
{
//bool flag = false;
int i = 0, j = pLen -k;
while(i < k)
{
if(p[i] == p[j])
{
i++;
j++;
}
else{
//flag = true;
k--;
break;
}
}
}
return k;
}
// 获得最大长度表
void getMaxTable(const char *p, int *table)
{
for(int i = 0; i < strlen(p); i++)
{
table[i] = getMaxFix(p, i+1);
}
}
参考文献:http://blog.csdn.net/v_july_v/article/details/7041827
作者:小村长 出处:http://blog.csdn.net/lu597203933 欢迎转载或分享,但请务必声明文章出处。
(新浪微博:小村长zack, 欢迎交流!
标签:kmp
原文地址:http://blog.csdn.net/lu597203933/article/details/41124815