KMP-看毛片算法 c++
2017-05-20 16:14
253 查看
kmp算法包括两步
1,计算next数组,即对要寻找的字符串标记值,例如abcabc,这边有六个字符,从a开始,将每一个字符与这个字符串开头开始匹配,第一个字符标记为0,第二个字符为b,明显与字符串开头a不相等,因此标记为0。第四个字符为a,与字符串开头a相等,因此标记为1,第五个字符为b,但他前面的字符被标记为1,因此第五个字符要与第1+1个字符相比较,如果相似,则标记为前一个字符标记的值+1.
贴代码
void cal_next(int *next,char tstr[100],int tlen)//这边传递了next数组的地址,要标记的字符串以及用于遍历的字符串长度;
{
next[0] = 0;//对第一个字符标记为0;
for (int i = 1; i < tlen; i++)//遍历,先查看前一个字符的标记值,如果为0,则将字符与第一个字符相比较,如果不为0,假设为x,则与第x+1个字符比较;
{
if (next[i - 1] == 0)
{
if (tstr[i] == tstr[0])
next[i] = 1;
else
next[i] = 0;
}
else
{
if (tstr[i] == tstr[next[i - 1]])
next[i] = next[i - 1] + 1;
else
next[i] = 0;
}
}
}2.进行匹配,如果匹配到目标数组中间发现后面不匹配,就访问最后一个匹配字符的标记值,例如主串abcabbbbbb,目标串abcabc假设匹配到第二个b的时候后面不匹配了,根据之前的求next数组方法,可以得到目标串。第二个b的标记值为2,这个b在目标串位置为第5个,因此下次要移动5-2次,即移动三个单位,此时目标串的a刚好对上主串第二个a。
贴代码
int kmp(char sstr[], char tstr[], int next[], int slen, int tlen)
{
int i = 0, j = 0;
while (i < slen)//遍历主串
{
bool flag = true;//立个flag,循环一下如果倒了,说明不匹配。
while (j < tlen)//遍历目标串
{
if (sstr[i] == tstr[j])//判断是否匹配
{
i++;
j++;
continue;
}
else
{
flag = false;
break;
}
}
if (flag == true)//看flag有不有倒。
return i - j + 1;
else
{
if (j == 0)//这个if语句之前没用,产生了bug,当j=0的时候,next[j-1]是next[-1],这时就会得到意外的值。
i = i + 1;
else
{
i = i + (j - next[j - 1]);
j = 0;
}
}
}
return -1;//如果匹配失败,则返回-1;
}-------------------------------------------切割-----------------下面是完整代码-----------------------------------------------------------
#include <iostream>
#include <string>
using namespace std;
void cal_next(int *next,char tstr[100],int tlen)
{
next[0] = 0;
for (int i = 1; i < tlen; i++)
{
if (next[i - 1] == 0)
{
if (tstr[i] == tstr[0])
next[i] = 1;
else
next[i] = 0;
}
else
{
if (tstr[i] == tstr[next[i - 1]])
next[i] = next[i - 1] + 1;
else
next[i] = 0;
}
}
}
int kmp(char sstr[], char tstr[], int next[], int slen, int tlen)
{
int i = 0, j = 0;
while (i < slen)
{
bool flag = true;
while (j < tlen)
{
if (sstr[i] == tstr[j])
{
i++;
j++;
continue;
}
else
{
flag = false;
break;
}
}
if (flag == true)
return i - j + 1;
else
{
if (j == 0)
i = i + 1;
else
{
i = i + (j - next[j - 1]);
j = 0;
}
}
}
return -1;
}
int main()
{
char sstr[100], tstr[100], ch = 0;
int slen, tlen;
cout << "Please enter the sstr:" << endl;
cin >> sstr;
again:
cout << "Please enter the ttstr:" << endl;
cin >> tstr;
slen = strlen(sstr);
tlen = strlen(tstr);
int next[100];
cal_next(next, tstr, tlen);
cout << "The next array is:";
for (int i = 0; i < tlen; i++)
cout << next[i];
cout << endl;
int situ;
situ = kmp(sstr, tstr, next, slen, tlen);
cout << "These two strings are matched in No." << situ << endl;
goto again;
system("pause");
return 0;
}
1,计算next数组,即对要寻找的字符串标记值,例如abcabc,这边有六个字符,从a开始,将每一个字符与这个字符串开头开始匹配,第一个字符标记为0,第二个字符为b,明显与字符串开头a不相等,因此标记为0。第四个字符为a,与字符串开头a相等,因此标记为1,第五个字符为b,但他前面的字符被标记为1,因此第五个字符要与第1+1个字符相比较,如果相似,则标记为前一个字符标记的值+1.
贴代码
void cal_next(int *next,char tstr[100],int tlen)//这边传递了next数组的地址,要标记的字符串以及用于遍历的字符串长度;
{
next[0] = 0;//对第一个字符标记为0;
for (int i = 1; i < tlen; i++)//遍历,先查看前一个字符的标记值,如果为0,则将字符与第一个字符相比较,如果不为0,假设为x,则与第x+1个字符比较;
{
if (next[i - 1] == 0)
{
if (tstr[i] == tstr[0])
next[i] = 1;
else
next[i] = 0;
}
else
{
if (tstr[i] == tstr[next[i - 1]])
next[i] = next[i - 1] + 1;
else
next[i] = 0;
}
}
}2.进行匹配,如果匹配到目标数组中间发现后面不匹配,就访问最后一个匹配字符的标记值,例如主串abcabbbbbb,目标串abcabc假设匹配到第二个b的时候后面不匹配了,根据之前的求next数组方法,可以得到目标串。第二个b的标记值为2,这个b在目标串位置为第5个,因此下次要移动5-2次,即移动三个单位,此时目标串的a刚好对上主串第二个a。
贴代码
int kmp(char sstr[], char tstr[], int next[], int slen, int tlen)
{
int i = 0, j = 0;
while (i < slen)//遍历主串
{
bool flag = true;//立个flag,循环一下如果倒了,说明不匹配。
while (j < tlen)//遍历目标串
{
if (sstr[i] == tstr[j])//判断是否匹配
{
i++;
j++;
continue;
}
else
{
flag = false;
break;
}
}
if (flag == true)//看flag有不有倒。
return i - j + 1;
else
{
if (j == 0)//这个if语句之前没用,产生了bug,当j=0的时候,next[j-1]是next[-1],这时就会得到意外的值。
i = i + 1;
else
{
i = i + (j - next[j - 1]);
j = 0;
}
}
}
return -1;//如果匹配失败,则返回-1;
}-------------------------------------------切割-----------------下面是完整代码-----------------------------------------------------------
#include <iostream>
#include <string>
using namespace std;
void cal_next(int *next,char tstr[100],int tlen)
{
next[0] = 0;
for (int i = 1; i < tlen; i++)
{
if (next[i - 1] == 0)
{
if (tstr[i] == tstr[0])
next[i] = 1;
else
next[i] = 0;
}
else
{
if (tstr[i] == tstr[next[i - 1]])
next[i] = next[i - 1] + 1;
else
next[i] = 0;
}
}
}
int kmp(char sstr[], char tstr[], int next[], int slen, int tlen)
{
int i = 0, j = 0;
while (i < slen)
{
bool flag = true;
while (j < tlen)
{
if (sstr[i] == tstr[j])
{
i++;
j++;
continue;
}
else
{
flag = false;
break;
}
}
if (flag == true)
return i - j + 1;
else
{
if (j == 0)
i = i + 1;
else
{
i = i + (j - next[j - 1]);
j = 0;
}
}
}
return -1;
}
int main()
{
char sstr[100], tstr[100], ch = 0;
int slen, tlen;
cout << "Please enter the sstr:" << endl;
cin >> sstr;
again:
cout << "Please enter the ttstr:" << endl;
cin >> tstr;
slen = strlen(sstr);
tlen = strlen(tstr);
int next[100];
cal_next(next, tstr, tlen);
cout << "The next array is:";
for (int i = 0; i < tlen; i++)
cout << next[i];
cout << endl;
int situ;
situ = kmp(sstr, tstr, next, slen, tlen);
cout << "These two strings are matched in No." << situ << endl;
goto again;
system("pause");
return 0;
}
相关文章推荐
- kmp(看毛片)算法详解
- kmp“看毛片”算法模板题
- HDU--杭电--1711--Number Sequence--KMP--水题,看毛片算法基础死方法运用
- 0050 KMP匹配算法的C++实现
- 【数据结构&&等差数列】KMP简介和算法的实现(c++ && java)
- 【字符串匹配】——KMP(看毛片算法)——深入讲解next数组的求解
- Kmp字符匹配算法优化C++实现
- C/C++——朴素的模式匹配算法和KMP模式匹配算法
- C++版字符串匹配算法之传统匹配算法加KMP字符串匹配算法
- C++ 改进的KMP模式匹配算法
- KMP-看毛片算法
- 算法导论-第32章-字符串匹配:Knuth-Morris-Pratt(KMP)算法C++实现
- 看毛片(KMP)算法简析
- 【数据结构&&等差数列】KMP简介和算法的实现(c++ && java)
- KMP 算法 C++
- 字符串匹配KMP(看毛片)算法
- KMP模式匹配算法 C++实现
- 看毛片算法 KMP
- C++ 实现搜索子串KMP 算法
- C++实现Kmp字符匹配算法的优化版