#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
#define INFEASIBLE -2
typedef struct
{
char *ch;
int length;
}String;
void String_Assign(String &S,char A[])
{
int i;
// if(S.ch)
// free(S.ch);
for(i=0;A[i]!='\0';i++);//求字符数组长度
if(i==0)//字符数组为空
{
S.ch=NULL;
S.length=i;
}
else
{
S.ch=(char *)malloc(i*sizeof(char));//申请空间并判断是否为空
if(!S.ch)
exit(OVERFLOW);
S.length=i;
for(i=0;i<S.length;i++)//逐一复制字符
S.ch[i]=A[i];
}
}//字符串赋值
void String_Init(String &S)
{
char A[255];
// printf("请输入字符串:\n");
gets(A);//输入字符数组
String_Assign(S,A);//给字符串赋值
}//输入赋值
int String_Length(String S)
{
return S.length;
}//返回字符串长度
void String_Show(String S)
{
int i;
for(i=0;i<S.length;i++)//逐个输出字符
printf("%c",S.ch[i]);
printf("\n");
}//出处字符串
/*
int String_Compare(String A,String B)
{
int i;
for(i=0;i<A.length&&i<B.length;i++)
if(A.ch[i]!=B.ch[i])//两个对应位置字符不相同时
break;
return A.ch[i]-B.ch[i];//返回两者差值
}//字符串比较
void String_Clear(String &S)
{
if(S.ch)
{
free(S.ch);//释放空间
S.ch=NULL;
}
S.length=0;
}//清空字符串
*/
void String_Contact(String &M,String S1,String S2)
{
int i,j;
// if(M.ch)
// free(M.ch);
M.ch=(char *)malloc((S1.length+S2.length)*sizeof(char));//申请新空间并判断是否成功
if(!M.ch)
exit(OVERFLOW);
M.length=S1.length+S2.length;//初始化长度
for(i=0;i<S1.length;i++)
M.ch[i]=S1.ch[i];//把第一个字符串逐个复制
for(j=0;j<S2.length;i++,j++)
M.ch[i]=S2.ch[j];//逐个复制第二个字符串
}//字符串链接
/*
int String_Sub(String S,String &Sub,int Pos,int len)
{
int i;
if(Pos<0||Pos>S.length||len<0||Pos+len-1>S.length)//截取位置与长度是否合法
return ERROR;
// if(Sub.ch)
// free(Sub.ch);
if(len==0)//截取长度为0的情况
{
Sub.ch=NULL;
Sub.length=0;
}
else
{
Sub.ch=(char *)malloc(len*sizeof(char));//申请空间并判断是否成功
if(!Sub.ch)
exit(OVERFLOW);
Sub.length=len;//初始化长度
for(i=0;i<Sub.length;i++,Pos++)//组个取值复制字符
Sub.ch[i]=S.ch[Pos];
}
return OK;
}//截取子串
int String_Replace(String &S,String T,String V)
{
int i,State;
String Sub,Temp;
for(i=0;i<S.length;i++)
{
State=String_Sub(S,Sub,i,T.length);//取相同长度子串
if(State==ERROR)
return ERROR;
if(String_Compare(Sub,T)==0)//判断两者是否相等
break;
}
State=String_Sub(S,Temp,0,i);//将替换子串前的子串取出
State=String_Sub(S,T,i+T.length,S.length-i-T.length);//将替换子串后的子串取出
String_Contact(Sub,Temp,V);//链接第一个子串和第二个子串
String_Contact(S,Sub,T);//将前两个子串和最后一个子串链接
return OK;
}//替换子串
int String_Delete(String &S,String T)
{
int i,State,flag;
String Sub,Temp;
if(T.length==0)
return ERROR;
for(i=S.length-T.length;i>=0;i--)
{
State=String_Sub(S,Sub,i,T.length);//逐个取子串
if(String_Compare(Sub,T)==0)//比较子串与目标串是否相等
{
flag=1;
State=String_Sub(S,Sub,0,i);//取子串前一个子串
State=String_Sub(S,Temp,i+T.length,S.length-i-T.length);//取子串后一个子串
String_Contact(S,Sub,Temp);//链接两个子串
}
}
if(flag==0)
return ERROR;
else
return OK;
}//删除子串
int String_BFmatch(String S,String T,int Pos[],int &N)
{
int i,State;
String Sub;
N=0;
Pos[0]=-1;
for(i=0;i<=S.length-T.length;i++)
{
State=String_Sub(S,Sub,i,T.length);//逐个取子串
if(State==ERROR)
return ERROR;
if(String_Compare(Sub,T)==0)//比较子串与目标串是否相等
Pos[N++]=i;//存储位置
}
if(Pos[0]==-1)
return ERROR;
else
return OK;
}//BF匹配算法
*/
void KMP_Next(String p,int next[])
{
int j,k;
next[0]=0;
for(k=0,j=1;j<p.length;j++)
{
while(k>0&&p.ch[k]!=p.ch[j])
k=next[k];//不等时递推寻找最长前缀
if(p.ch[k]==p.ch[j])
k++;//相等时,前缀直接加1
next[j]=k;
}
}//KMP算法跳转数组
int String_KMPmatch(String S,String T,int Pos[],int &N)
{
int *next,i,j=0;
next=(int *)malloc(T.length*sizeof(int));//申请空间构建next数组
KMP_Next(T,next);
N=0;
Pos[0]=-1;
for (i=0;i<S.length;i++)
{
while (j>0&&S.ch[i]!=T.ch[j])//逐个比较模式串与主串
j=next[j];//不匹配就跳转
if(S.ch[i]==T.ch[j])
j++;//匹配则移位
if (j==T.length)
{
Pos[N++]=i-j+1;//存储位置
j=0;
}
}
if(Pos[0]==-1)
return ERROR;
else
return OK;
}//KMP算法
/*
void BM_Badc(String S,int BC[])
{
int i;
for(i=0;i<256;i++)//将所有字符都赋值为最大距离
BC[i]=S.length;
for(i=0;i<S.length;i++)//将模式串中的字符从新覆盖赋值为到串尾的距离
BC[S.ch[i]]=S.length-i-1;
}//BM算法坏字符数组
void GoodS_Suffix(String S,int Suffix[])
{
int i,j;
Suffix[S.length-1]=S.length;
for(i=S.length-2;i>=0;i--)
{
j=i;
while(j>0&&S.ch[j]==S.ch[S.length-i-1+j])//求好后缀的长度
j--;
Suffix[i]=i-j;
}
}//BM算法好后缀长度数组
void BM_Goods(String S,int GS[])
{
int i,j,*Suffix;
Suffix=(int *)malloc(S.length*sizeof(int));//申请好后缀长度数组
if(!Suffix)
exit(INFEASIBLE);
GoodS_Suffix(S,Suffix);
for(i=0;i<S.length;i++)//不存在匹配前缀则直接跳转模式串长度
GS[i]=S.length;
j=0;
for(i=S.length-1;i>=0;i--)
if(Suffix[i]==i+1)
for (;j<S.length-1-i;j++)
if (GS[j]==S.length)
GS[j]=S.length-1-i;//存在子串
for (i=0;i<=S.length-2;i++)
GS[S.length-1-Suffix[i]]=S.length-1-i;//存在相同的串
}//BM算法好后缀数组
int String_BMmatch(String S,String T,int Pos[],int &N)
{
int i, j,*GS,*BC;
BC=(int *)malloc(256*sizeof(int));
if(!BC)
exit(INFEASIBLE);
GS=(int *)malloc(T.length*sizeof(int));
if(!GS)
exit(INFEASIBLE);
BM_Badc(T,BC);
BM_Goods(T,GS);//申请好后缀与坏字符空间
j=0;
N=0;
Pos[0]=-1;
while (j<=S.length-T.length)
{
for (i=T.length-1;i>=0&&T.ch[i]==S.ch[i+j];i--);//从模式串尾部开始比较
if (i<0)
{
Pos[N++]=j;//存储位置
j+=GS[0];//寻找下一个目标串
}
else
j+=GS[i]>(BC[S.ch[i+j]]-T.length+1+i)?GS[i]:(BC[S.ch[i+j]]-T.length+1+i);//匹配失败时跳转最大长度
}
if(Pos[0]==-1)
return ERROR;
return OK;
}//BM算法
*/
void String_Read(String &S)
{
FILE *fp;
char str[1000];
String Temp;
fp=fopen("test.txt","r");//打开文件
if(!fp)
exit(INFEASIBLE);
fgets(str,100,fp);
String_Assign(S,str);//读取文件第一行并存储
S.length--;//删除尾部换行符
while(fgets(str,100,fp))
{
String_Assign(Temp,str);//逐个读取文件每行的字符串
Temp.length--;//删除尾部换行符
String_Contact(S,S,Temp);//链接
}
fclose(fp);
}//读取文件
int main()
{
String S,T;
int Pos[100],N,State,i;
String_Read(S);
String_Show(S);
printf("\n请输入查找字符串:");
String_Init(T);
/* printf("----------B F算法----------\n");
State=String_BFmatch(S,T,Pos,N);
if(State==ERROR)
printf("查找不到!\n\n");
else
{
for(i=0;i<N;i++)
printf("在位置%03d处发现目标字符串!\n",Pos[i]);
printf("\n");
}*/
printf("----------KMP算法----------\n");
State=String_KMPmatch(S,T,Pos,N);
if(State==ERROR)
printf("查找不到!\n\n");
else
{
for(i=0;i<N;i++)
printf("在位置%03d处发现目标字符串!\n",Pos[i]);
printf("\n");
}
/* printf("----------B M算法----------\n");
State=String_BMmatch(S,T,Pos,N);
if(State==ERROR)
printf("查找不到!\n\n");
else
{
for(i=0;i<N;i++)
printf("在位置%03d处发现目标字符串!\n",Pos[i]);
printf("\n");
}*/
return 0;
}
数据结构(c++) 串的匹配BF->KMP->BM算法
最新推荐文章于 2023-06-05 04:41:53 发布