串 可以理解为内容受限的线性表
主要讲解两个算法,一个是BF算法,朴素的模式匹配法(亦称暴力破解法);另一个是KMP算法,这个算法是三位前辈创的,避免了重复遍历的情况。另外是在KMP算法的基础上进行的优化,只需改动内置函数next()。
/*
BF算法:也称暴力破解法,通过穷举法的思路进行比对。
可以理解为双指针。 时间复杂度O(n*m)
KMP算法:通过next数组记录 模式串 的重复部分,从而将时间复杂度提高 O(n+m);
*/
#include<iostream>
using namespace std;
int BF_Index(string S, string T, int pos)
{
int i = pos;
int j = 0;
int slen = S.size();
int tlen = T.size();
while (i<slen && j< tlen)
{
if (S[i] == T[j]) // 主串和子串匹配则继续下一个字符
{
i++;
j++;
}
else // 不匹配则主串回溯到开始前的下一个字符,且子串重新开始
{
i = i - j + 1;
j = 0;
}
}
if (j >= tlen) return i - tlen; // j等于tlen说明子串遍历了所有字符都与主串相同,下标返回为 主串此时的下标 - 子串的长度
else return 0; // 否则说明,主串遍历所有,也没有相同的
}
void Get_Next(string T,int *next)
{
int i=0,j=-1;
int tlen = T.size();
next[0] = -1;
while (i < tlen)
{
if (j==-1 || T[i] == T[j])
{
++i;
++j;
next[i] = j;
}
else j = next[j]; // 若字符不相等,则j值回溯
}
}
void Get_Nextval(string T, int* next)
{
int i = 0, j = -1;
int tlen = T.size();
next[0] = -1;
while (i < tlen)
{
if (j == -1 || T[i] == T[j])
{
++i;
++j;
if (T[i] != T[j]) next[i] = j;
else next[i] = next[j];
}
else j = next[j]; // 若字符不相等,则j值回溯
}
}
int KMP_index(string S, string T, int pos)
{
int i = pos;
int j = 0;
int slen = S.size();
int tlen = T.size();
int next[255];
Get_Nextval(T, next);
while (i < slen && j < tlen)
{
if (S[i] == T[j]) // 主串和子串匹配则继续下一个字符
{
i++;
j++;
}
else // 不匹配
{
j = next[j];
}
}
if (j >= tlen - 1) return i - tlen;
else return 0;
}
int main()
{
string s = "00000000001";
string t = "00001";
int index = BF_Index(s, t, 0);
cout << "BF算法:" << index << endl;
index = KMP_index(s, t, 0);
cout << "KMP算法:" << index << endl;
return 0;
}