您的位置:首页 > 编程语言 > C语言/C++

C/C++——朴素的模式匹配算法和KMP模式匹配算法

2017-04-30 16:44 399 查看

朴素的模式匹配算法

其实就是一个一个往下匹配,没有任何优化,在好的情况下时间复杂度为O(n+m),在最求的情况下时间复杂度为O((n-m+1)*m)。

代码实现:

//在主串s中找子串t,若找到返回字串在主串中的索引;若没找到返回-1
#include <iostream>
#include <string>

using namespace std;

int Index(string s, string t){
int lens = s.length();//计算串s、t的长度
int lent = t.length();
int i = 0;
int j = 0;
while (i < lens&&j < lent){//如果i、j都各自小于lens和lent
if (t[j] == s[i]){//如果子串的t[j]和主串的s[i]相等
++i;//各自索引都自增
++j;
}
else{//否则,主串的索引比刚开始后移一个;子串的索引变为0
i = i - j + 1;
j = 0;
}
}
if (j == lent){//如果最j和lent的大小一样,证明找到了,返回子串在主串中的索引
return i - lent;
}
else{//否则返回-1
return -1;
}
}

int main(){
string s = "goodgoogle";
string t = "google";
int pos = Index(s, t);
if (pos != -1){
cout << "find " << t << " at the index " << pos << " of " << s << endl;
}
else{
cout << "can't find " << t << " in " << s << endl;
}
return 0;
}


KMP模式匹配算法

先对子串t进行next判断,得到一个next数组,再进行比较。时间复杂度为O(n+m)

代码实现:

//在主串s中找子串t,若找到返回字串在主串中的索引;若没找到返回-1
#include <iostream>
#include <string>

using namespace std;

void get_next(string t, int *next);
int Index_KMP(string s, string t);

int main(){
string s = "ababadeababaaabadf";
string t = "ababaaaba";
int pos = Index_KMP(s, t);
if (pos != -1){
cout << "find " << t << " at the index " << pos << " of " << s << endl;
}
else{
cout << "can't find " << t << " in " << s << endl;
}

return 0;
}

int Index_KMP(string s, string t){
int lens = s.length();
int lent = t.length();
int *next = new int[lent];
get_next(t, next); //对子串t作分析,得到next数组
//cout << "next: ";    //输出next测试而已
//for (int i = 0; i < lent; ++i){
//  cout << next[i];
//}
//cout << endl;
int i = 0;
int j = 0;
while (i < lens&&j < lent){//两字母相等则继续,与朴素算法增加了j==0的判断
if (j == 0 || t[j] == s[i]){
++i;
++j;
}
else{
j = next[j-1];//j退回合适位置,i值不变
}
}
if (j == lent){//如果最j和lent的大小一样,证明找到了,返回子串在主串中的索引
return i - lent;
}
else{//否则返回-1
return -1;
}
}

void get_next(string t, int *next){
int lent = t.length();
int i = 0;
int j = 0;
next[0] = 0;
while (i < lent){//i小于t的长度
if (j == 0 || t[i] == t[j - 1]){//t[i]表示后缀的单个字符
++i;                      //t[j]表示前缀的单个字符
++j;
next[i] = j;
}
else{
j = next[j - 1];   //若字符不相同,则j值回溯
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: