实现顺序串的各种模式匹配算法
一、实验内容
编写一个程序,实现顺序串的各种模式匹配运算,并在此基础上完成以下功能。
(1)建立目标串s="abcabcdabcdeabcdefabcdefg”和模式串t="abcdeabcdefab”。
(2)采用简单匹配算法求t在s中的位置。
(3)由模式串t求出next数组值和nextval数组值。
(4)采用KMP算法求t在s中的位置。
(5)采用改进的KMP算法求t在s中的位置。
二、实验目的
本实验旨在通过编写一个程序实现顺序串的各种模式匹配运算,包括建立目标串和模式串、简单匹配算法、KMP算法以及改进的KMP算法等。通过这个实验,希望学生能够深入理解模式匹配算法的原理和实现方式,并且掌握模式匹配算法的设计和实现技巧。
三、实验设计方案
1.建立目标串s和模式串t
使用一个字符数组来存储目标串s和模式串t。在程序中,可以定义两个字符数组并分别初始化为"abcabcdabcdeabcdefabcdefg"和"abcdeabcdefab"。
2.简单匹配算法求t在s中的位置
使用简单匹配算法,通过循环遍历目标串s和模式串t,比较每个字符是否相等。如果相等,则继续向后遍历;如果不相等,则返回-1。在匹配成功的情况下,返回匹配的位置。
3.求next数组值和nextval数组值
使用KMP算法,需要定义两个数组:next数组和nextval数组。next数组表示在匹配失败时,目标串s需要向右移动的步数;nextval数组表示在匹配失败时,模式串t需要向右移动的步数。可以通过预处理模式串t来计算这两个数组的值。
4.采用KMP算法求t在s中的位置
使用KMP算法,通过循环遍历目标串s和模式串t,比较每个字符是否相等。如果相等,则继续向后遍历;如果不相等,则根据next数组和nextval数组的值进行匹配失败的处理。在匹配成功的情况下,返回匹配的位置。
5.采用改进的KMP算法求t在s中的位置
改进的KMP算法是在KMP算法的基础上,通过记录已经比较过的字符的下一个字符来优化nextval数组的计算。具体实现可以参考相关算法书籍或网络教程。
在程序中,可以分别实现以上五个功能模块,并通过调用函数的方式实现顺序串的各种模式匹配运算。需要注意的是,在实现过程中需要考虑边界条件和错误处理等问题,以保证程序的正确性和健壮性。
四、代码实现
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 50
typedef struct{
char data[MaxSize];
int length;
}SqString;
//生成串
void StrAssign(SqString &s,char cstr[]){
int i;
for(i=0;cstr[i]!='\0';i++)
s.data[i]=cstr[i];
s.length=i;
}
//销毁串
void DestroyStr(SqString &s){
}
//串的复制
void StrCopy(SqString &s,SqString t){
int i;
for(i=0;i<t.length;i++)
s.data[i]=t.data[i];
s.length=t.length;
}
//判断串相等
bool StrEqual(SqString s,SqString t){
bool same=true;
int i;
if(s.length!=t.length) same=false;
else{
for(i=0;i<s.length;i++)
if(s.data!=t.data){
same=false;
break;
}
}
return same;
}
//求串的长
int StrLength(SqString s){
return s.length;
}
//串的连接
SqString Concat(SqString s,SqString t){
SqString str;
int i;
str.length=s.length+t.length;
for(i=0;i<s.length;i++)
str.data[i]=s.data[i];
for(i=0;i<t.length;i++)
str.data[i+s.length]=t.data[i];
return str;
}
//求子串
SqString SubStr(SqString s,int i,int j){
int k;
SqString str;
str.length=0;
if(i<=0||i>s.length||j<0||i+j-1>s.length)
return str;
for(k=i-1;k<i+j-1;k++)
str.data[k-i+1]=s.data[k];
str.length=j;
return str;
}
//子串的插入
SqString InsStr(SqString s1,int i,SqString s2){
int j;
SqString str;
str.length=0;
if(i<=0||i>s1.length+1)return str;
for(j=0;j<i-1;j++) str.data[j]=s1.data[j];
for(j=0;j<s2.length;j++) str.data[i+j-1]=s2.data[j];
for(j=i-1;j<s1.length;j++) str.data[s2.length+j]=s1.data[j];
str.length=s1.length+s2.length;
return str;
}
//子串的删除
SqString DelStr(SqString s,int i,int j){
int k;
SqString str;
str.length=0;
if(i<=0||i>s.length||i+j-1>s.length)return str;
for(k=0;k<i-1;k++) str.data[k]=s.data[k];
for(k=j+i-1;k<s.length;k++) str.data[k-j]=s.data[k];
str.length=s.length-j;
return str;
}
//子串的替换
SqString InsStr(SqString s,int i,int j,SqString t){
int k;
SqString str;
str.length=0;
if(i<=0||i>s.length||i+j-1>s.length)return str;
for(k=0;k<i-1;k++) str.data[k]=s.data[k];
for(k=0;k<t.length;k++) str.data[i+k-1]=t.data[k];
for(k=j+i-1;k<s.length;k++) str.data[k-j+t.length]=s.data[k];
str.length=s.length-j+t.length;
return str;
}
//输出串
void DispStr(SqString s){
int i;
if(s.length>0){
for(i=0;i<s.length;i++)
printf("%c",s.data[i]);
printf("\n");
}
}
//BF算法
int BF(SqString s,SqString t){
int j=0,i=0;
while(i<s.length && j<t.length){
if(s.data[i]==t.data[j]){
i++;j++;
}else{
i=i-j+1;j=0;
}
}
if(j>=t.length)
return(i-t.length);
else return -1;
}
//KMP算法
//求串t的next数组
void GetNext(SqString t,int next[]){
int j,k;
j=0;k=-1;
next[0]=-1;
while(j<t.length-1){
if(k==-1 || t.data[j]==t.data[k]){
j++;k++;
next[j]=k;
}
else k=next[k];
}
}
//KMP
int KMPIndex(SqString s,SqString t){
int next[MaxSize],i=0,j=0;
GetNext(t,next);
while(i<s.length && j<t.length){
if(j==-1||s.data[i]==t.data[j]){
i++;j++;
}
else j=next[j];
}
if(j>=t.length) return(i-t.length);
else return -1;
}
//Nextval
void GetNextval(SqString t,int nextval[]){
int j,k;
j=0;k=-1;
nextval[0]=-1;
while(j<t.length){
if(k==-1 || t.data[j]==t.data[k]){
j++;k++;
if(t.data[j]!=t.data[k])
nextval[j]=k;
else
nextval[j]=nextval[k];
}
else k=nextval[k];
}
}
//KMP
int KMPIndex1(SqString s,SqString t){
int nextval[MaxSize],i=0,j=0;
GetNextval(t,nextval);
while(i<s.length && j<t.length){
if(j==-1||s.data[i]==t.data[j]){
i++;j++;
}
else j=nextval[j];
}
if(j>=t.length) return(i-t.length);
else return -1;
}
int main(){
SqString s,t;
//建立串s,t
printf("1、建立串s,t\n");
char cstr[]={'a','b','c','a','b','c','d','a','b','c','d','e','a','b','c','d','e','f','a','b','c','d','e','f','g'};
char cstr1[]={'a','b','c','d','e','a','b','c','d','e','f','a','b'};
StrAssign(s,cstr);
StrAssign(t,cstr1);
printf("\n");
//输出串s
printf("2、输出串s:");
DispStr(s);
printf("\n");
//输出串t
printf("3、输出串t:");
DispStr(t);
printf("\n");
//t的next数组
printf("t的next数组:");
int next[t.length];
GetNext(t,next);
for(int i=0;i<t.length;i++)
printf("%d\t",next[i]);
printf("\n");
//t的nextval数组
printf("t的nextval数组:");
int nextval[t.length];
GetNextval(t,nextval);
for(int i=0;i<t.length;i++)
printf("%d\t",nextval[i]);
printf("\n");
//BF算法
KMPIndex(s,t);
printf("%d\n",KMPIndex(s,t));
KMPIndex1(s,t);
printf("%d\n",KMPIndex1(s,t));
return 0;
}
五、运行结果