数据结构(c++) 串的匹配BF->KMP->BM算法

来源:互联网 发布:腊鸡网络用语 编辑:程序博客网 时间:2024/05/16 12:26
#include<stdio.h> #include<stdlib.h>#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define OVERFLOW -1#define INFEASIBLE -2typedef 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;}
阅读全文
0 0