版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_36669549/article/details/84863528
编写程序比较Brute-Force算法与KMP算法的效率。例如,主串S="bcdamnbacabaabaabacababafabacabababab",模式串T="abaabacababa",统计Brute-Force算法与KMP算法在匹配过程中的比较次数并输出模式串的next值。
【分析】
通过主串的模式匹配比较Brute-Force算法与KMP算法的效果。朴素的Brute-Force算法也是常用的算法,毕竟它不需要计算next函数值。KMP算法在模式串与主串存在许多部匹配的情况下,其优越性才会显示出来。
SeqString.h
#pragma once
#include <iostream>
using namespace std;
#define MAXSIZE 100
#define MaxLen 50
//存储结构
typedef struct
{
char str[MAXSIZE];
int Length;
}SeqString;
//串的赋值
void StrAssign(SeqString *S, char cstr[])
{
int i=0;
for (i = 0; cstr[i] != '\0';i++)
{
S->str[i] = cstr[i];
}
S->Length = i;
}
//判断串是否为空
int StrEmpty(SeqString S)
{
if (S.Length==0)
{
return 1;
}
else
{
return 0;
}
}
//求串的长度
int StrLength(SeqString S)
{
return S.Length;
}
//串的复制
void StrCopy(SeqString *T, SeqString S)
{
int i;
for (i = 0; i < S.Length;i++)
{
T->str[i] = S.str[i];
}
T->Length = S.Length;
}
//比较两个串的大小
int StrCompare(SeqString S, SeqString T)
{
int i;
for (i = 0; i < S.Length&&T.Length;i++)
{
if (S.str[i]!=T.str[i])
{
return (S.str[i] - T.str[i]);
}
}
return (S.Length - T.Length);
}
/*在串的第pos位置插入串T。若插入成功,返回1;否则返回0.*/
/*串的插入操作具体实现分为3种情况:
第1种情况,在S中插入T后串长不超过能容纳的最长字符,即S->Length+T.Length<=MaxLen
则先将串S中pos后的字符向后移动Len个位置,然后将串T插入S中即可;
第2种情况,若将T插入S后,串长超过能容纳的最长字符但T能完全插入S中,即S->Length+T.Length>MaxLen
则将串S中pos后的字符往后移动Len个位置后,S中的部分字符被舍弃;
第3种情况,将T插入S中,有S->Length+T.Length>MaxLen且T不能完全被插入S中
则T中部分字符和S中第Len位置以后的字符均被舍弃。*/
int StrInsert(SeqString *S, int pos, SeqString T)
{
int i;
if (pos < 0||pos-1>S->Length)
{
cout << "插入位置不正确!";
return 0;
}
if (S->Length + T.Length <=MaxLen)
{
for (i = S->Length + T.Length - 1; i >= pos + T.Length - 1;i--)
{
S->str[i] = S->str[i - T.Length];
}
for (i = 0; i < T.Length;i++)
{
S->str[pos + i - 1] = T.str[i];
}
S->Length = S->Length + T.Length;
return 1;
}
else if (pos+T.Length<=MaxLen)
{
for (i = MaxLen - 1; i > T.Length + pos - 1;i--)
{
S->str[i] = S->str[i - T.Length];
}
for (i = 0; i < T.Length;i++)
{
S->str[i + pos - 1] = T.str[i];
}
S->Length = MaxLen;
return 0;
}
else
{
for (i = 0; i < MaxLen - pos;i++)
{
S->str[i + pos - 1] = T.str[i];
}
S->Length = MaxLen;
return 0;
}
}
/*删除串S中pos开始的len个字符*/
int StrDelete(SeqString *S, int pos, int len)
{
int i;
if (pos<0||len<0||pos+len-1>S->Length)
{
cout << "删除位置不合法,参数len不合法!";
return 0;
}
else
{
for (i = pos + len; i <= S->Length - 1;i++)
{
S->str[i - len] = S->str[i];
}
S->Length = S->Length - len;
return 1;
}
}
/*将串S连接在串T的末尾。串的连接操作可以分为两种情况:
第1种,连接后串长T->Length+S.Length≤MaxLen,则直接将串S连接在串T的尾部;
第2种,连接后串长T->Length+S.Length≥MaxLen且串的长度<MaxLen,则串S会有字符丢失。*/
int StrConcat(SeqString *T, SeqString S)
{
int i, flag;
if (T->Length+S.Length<=MaxLen)
{
for (i = T->Length; i < T->Length + S.Length;i++)
{
T->str[i] = S.str[i - T->Length];
}
T->Length = T->Length + S.Length;
flag = 1;
}
else if(T->Length<MaxLen)
{
for (i = T->Length; i < MaxLen;i++)
{
T->str[i] = S.str[i - T->Length];
}
T->Length = MaxLen;
flag = 0;
}
return flag;
}
/*清空串操作*/
void StrClear(SeqString *S)
{
S->Length = 0;
}
main.cpp
#include <stdlib.h>
#include <string.h>
#include "SeqString.h"
#include <iostream>
#include <iomanip>
int B_FIndex(SeqString S,int pos,SeqString T,int *count);
int KMP_Index(SeqString S,int pos, SeqString T, int next[],int *count);
void GetNext(SeqString T,int next[]);
void PrintArray(SeqString T,int next[],int length);
void main()
{
SeqString S, T;
int count1 = 0, count2 = 0, find;
int next[40];
StrAssign(&S, "bcdamnbacabaabaabacababafabacabababab");
StrAssign(&T, "abaabacababa");
GetNext(T, next);
cout << "模式串T的next和改进后的next值:" << endl;
PrintArray(T, next, StrLength(T));
find = B_FIndex(S, 1, T, &count1);
if (find>0)
{
cout << "Brute-Force算法的比较次数为" << count1 << endl;
}
find = KMP_Index(S, 1, T, next, &count2);
if (find>0)
{
cout << "利用next的KMP算法的比较次数为:" <<count2<< endl;
}
StrAssign(&S, "bcdabcacbdaacabcabaacaabcabcabcbccbcabccbdcabcb");
StrAssign(&T, "abcabcbc");
GetNext(T, next);
cout << "模式串T的next和改进后的next值:" << endl;
PrintArray(T, next, StrLength(T));
find = B_FIndex(S, 1, T, &count1);
if (find > 0)
{
cout << "Brute-Force算法的比较次数为" << count1 << endl;
}
find = KMP_Index(S, 1, T, next, &count2);
if (find > 0)
{
cout << "利用next的KMP算法的比较次数为:" << count2 << endl;
}
system("pause");
}
void PrintArray(SeqString T, int next[], int length)
{
int j;
cout << "j:\t\t";
for (j = 0; j < length;j++)
{
cout << setw(3) << j;
}
cout << endl;
cout << "模式串:\t";
for (j = 0; j < length;j++)
{
cout << setw(3) << T.str[j];
}
cout << endl;
cout << "next[j]:\t";
for (j = 0; j < length;j++)
{
cout << setw(3) << next[j];
}
cout << endl;
}
int B_FIndex(SeqString S, int pos, SeqString T, int *count)
{
int i, j;
i = pos - 1;
j = 0;
*count = 0;
while (i<S.Length&&j<T.Length)
{
if (S.str[i]==T.str[j])
{
i++;
j++;
}
else
{
i = i - j + 1;
j = 0;
}
(*count)++;
}
if (j>=T.Length)
{
return i - j + 1;
}
else
{
return -1;
}
}
int KMP_Index(SeqString S, int pos, SeqString T, int next[], int *count)
{
int i, j;
i = pos - 1;
j = 0;
*count = 0;
while (i<S.Length&&j<T.Length)
{
if (j==-1||S.str[i]==T.str[j])
{
i++;
j++;
}
else
{
j = next[j];
}
(*count)++;
}
if (j>=T.Length)
{
return i - T.Length + 1;
}
else
{
return -1;
}
}
void GetNext(SeqString T, int next[])
{
int j, k;
j = 0;
k = -1;
next[0] = -1;
while (j<T.Length)
{
if (k==-1||T.str[j]==T.str[k])
{
j++;
k++;
next[j] = k;
}
else
{
k = next[k];
}
}
}
结果: