这里写自定义目录标题
BF算法和KMP算法C++实现
KMP算法主要思想:
利用查找目标串上一次比较时的信息,以提高搜索速度。
完整代码:
// BF & KMP
#include <cstdlib>
#include <iostream>
#include <string>
#include<ctime>
using namespace std;
// 函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define MAXLEN 100
#define CHUNKSIZE 80
//Status 是函数的类型,其值是函数结果状态代码
typedef int Status;
#define MAXSIZE 100
typedef int ElemType;
typedef struct {
ElemType* elem;
int length;
} SqList; //顺序表类型
Status InitList_Sq(SqList& L) { //构造一个空的顺序表L
L.elem = new ElemType[MAXSIZE]; //为顺序表分配空间
if (!L.elem) exit(OVERFLOW); //储存分配失败
L.length = 0; //空表长度为0
return OK;
}
void DestroyList(SqList& L) {
if (L.elem) delete L.elem; //释放存储空间
}
void ClearList(SqList& L) {
L.length = 0; //将线性表的长度置为0
}
int GetLength(SqList L) {
return (L.length);
}
int IsEmpty(SqList L) {
if (L.length == 0) return 1;
else return 0;
}
int GetElem(SqList L, int i, ElemType& e) {
if (i<1 || i>L.length) return ERROR;
// 判断i值是否合理,若不合理,返回ERROR
e = L.elem[i-1]; //第i-1的单元存储着第i个数据
return OK;
}
// 按值查找
int LocateElem(SqList L, ElemType e) {
//在线性表L中查找值为e的数据元素,返回其序号
for (int i = 0; i < L.length; i++)
if (L.elem[i] == e) return i + 1; //查找成功,返回序号
return 0;//查找失败,返回0
}
// 插入算法
Status ListInsert_Sq(SqList& L, int i, ElemType e) {
if (i<1 || i>L.length + 1)return ERROR; //i值不合法
if (L.length == MAXSIZE)return ERROR; //当前存储空间已满
for (int j = L.length - 1; j >= i - 1; j--)
L.elem[j + 1] = L.elem[j]; //插入位置及之后的元素后移
L.elem[i-1] = e; //将新元素e放入第i个位置
L.length++; //表长增1
return OK;
}
// 顺序存储结构
typedef struct {
char ch[MAXLEN + 1]; // 存储串的一维数组
int length; // 串的当前长度
}SString;
// 块链存储结构
typedef struct Chunk {
char ch[CHUNKSIZE];
struct Chunk* next;
}Chunk;
typedef struct {
Chunk* head, * tail; // 串的头指针和尾指针
int curlen; // 串的当前长度
}LString;
Status StrAssign(SString &S,string s) {
int s_length;
s_length = s.length();
for (int i = 1; i <= s_length; i++) {
S.ch[i] = s[i-1];
};
S.length = s_length;
return OK;
}
// 串的模式匹配算法
// BF 暴力,时间效率低
int Index_BF(SString S, SString T,int pos) {
int i = pos; int j = 1;
while (i <= S.length && j <= T.length) {
if (S.ch[i] == T.ch[j]) {
++i;
++j;
}// 主串和子串依次匹配下一个字符
else {
i = i - j + 2; j = 1;
}// 主串、子串指针回溯重新开始下一次匹配
}
if (j >= T.length)return i - T.length;
else return 0;
}
// KMP 速度快,理解难
int Index_KMP(SString S, SString T, int pos,SqList next) {
int i = pos; int j = 1;
while (i <= S.length && j <= T.length) {
if (j == 0 || S.ch[i] == T.ch[j]) {
i++; j++;
}
else {
GetElem(next, j, j);
}
}
if (j > T.length)return i - T.length; /*匹配成功*/
else return 0; /*返回匹配不成功标志*/
}
int get_next(SString T,SqList &next) {
ListInsert_Sq(next, 1, 0);
int i = 1;int j = 0;
while (i < T.length) {
// abcabcd
if (j == 0 || T.ch[i] == T.ch[j]) {
++i; ++j;
ListInsert_Sq(next, i, j);
}
else {
GetElem(next, j, j);
};
int e;
GetElem(next, i, e);
}
cout << endl;
return OK;
}
int main(){
SString S;
SString T;
string s = "bcabcdbcabcdefefcabcbcabcdefabcdefaabcabcabcdefg";
string t = "abcabcd";
clock_t startTime;
clock_t endTime;
int pos = 1;
StrAssign(S, s);
StrAssign(T, t);
SqList next;
InitList_Sq(next);
get_next(T, next);
cout << "next值:" << endl;
for (int i = 1; i <= t.length(); i++){
int e;
GetElem(next, i, e);
cout << e;
}
cout << endl;
startTime = clock();
int index_KMP = Index_KMP(S, T, pos, next);
endTime = clock();
double KMP_time = endTime - startTime;
startTime = clock();
int index_BF = Index_BF(S, T, pos);
endTime = clock();
double BF_time = endTime - startTime;
cout << "计算完毕" << endl;
cout << "index_BF: " << index_BF << endl;
cout << "time_BF: " << BF_time << endl;
cout << "index_KMP: " << index_KMP << endl;
cout << "time_KMP: " << KMP_time << endl;
system("pause");
return 0;
}