DataStructure-5-字符串

来源:互联网 发布:6603棋牌 数据库 编辑:程序博客网 时间:2024/06/06 04:04

5.1 朴素的模式匹配算法(BF算法(Brute Force))

     5.1.1原理分析

   


    5.1.2 代码实现


#include <stdio.h>

int BF(char S[],char T[]);

int main(void)
{
    //主串
    char S[] = "abcabcacb";
    //模式串
    char T[] = "abcac";

    //匹配查找
    printf("BF:%d\n",BF(S,T));

}

int BF(char S[],char T[])
{
    int i=0,j=0;
    //当S没有结束并且T也没有结束
    while(S[i] != '\0' && T[j] != '\0')
    {
        if(S[i]==T[j])
        {
            i++;
            j++;
        }
        else            //i和j分别回溯
        {
            i = i-j+1;
            j=0;
        }
    }
    if(T[j]=='\0')   //匹配成功,返回本次匹配的开始位置(不是下标)
    {
        return i-j+1;
    }else{
        return 0;
    }
}


5.2 KMP算法

  5.2.1 原理分析

   基本思想:主串不回溯

 



 

版本一:j从0开始,next从-1开始 (我比较喜欢j从0开始大笑)


 

列如:主串S=“ababaababcb”, 模式T=“ababc”,则该模式的next值计算如下:


j=0时,next[0]=-1;

j=1时,此时j由0到j-1的串只有“a”,属于其他情况next[1]=0;

j=2时, 此时j由0到j-1的串有“ab”,T[0]!=T[1],则next[2]=0;

j=3时, 此时j由0到j-1的串有“aba”,T[0]=T[2],则next[3]=1;

j=4时, 此时j由0到j-1的串有“abab”,T[0] T[1]=T[2] T[3],则next[4]=2;



版本二:J从1开始,next从0开始:

       


 2.5.2 KMP算法的实现

#include <stdio.h>

void GetNext(char T[],int *next);
int KMP1(char S[],char T[]);
int length(char L[]);

int main(void)
{
    //主串
    char S[] = "ababaababcb";
    //模式串
    char T[] = "ababc";
    //匹配查找
    printf("KMP1:%d\n",KMP1(S,T));

    return 0;
}
/*求字符串长度*/
int length(char L[])
{
    int i=0;
    while(L[i] != '\0')
    {
        i++;
    }
    return i;
}

//*next数组*/
void GetNext(char T[],int *next)
{
    int j=0,k=-1;
    next[0]=-1;
    while(j < length(T))
    {
        if(k==-1 || T[j] == T[k])
        {
            ++j;
            ++k;
            next[j]=k;
        }else{
            k=next[k];
        }
    }
}

int KMP1(char S[],char T[])
{
    int i=0,j=0;
    int next[5];
    GetNext(T,next);
    /*当S没有结束并且T也没有结束*/
    while(i < length(S) && j < length(T))
    {
        if(j==-1 || S[i]==T[j])
        {
            ++i;
            ++j;
        }
        else            /*j回溯*/
        {
            j=next[j];
        }
    }
    if(j >= length(T))   /*匹配成功,返回本次匹配的开始位置(不是下标)*/
    {

        printf("i=%d,j=%d,T[j]=%c \n",i,j,T[j]);
        return i-j+1;
    }else{
        return 0;
    }
}




改进kmp算法:

       注:此处讲解j是从1开始的,只是演示思路,程序设计还是以j=0开始


有以上的思路理解,对kmp算法改进如下:
  j
0
1
2
3
4
T
 a
 b
 a
 b
 c
next[j]
-1
0
0
1
2
nextval[j]
-1
 0
-1
 0
 2

#include <stdio.h>

void GetNextVal(char T[],int next[]);
int KMP2(char S[],char T[]);
int length(char L[]);

int main(void)
{
    //主串
    char *S = "ababaababcb";
    //模式串
    char *T = "ababc";
    //匹配查找
    printf("KMP2:%d\n",KMP2(S,T));

    return 0;
}

/*求字符串长度*/
int length(char L[])
{
    int i=0;
    while(L[i] != '\0')
    {
        i++;
    }
    return i;
}


/*改进kmp算法的next数组*/
void GetNextVal(char T[],int next[])
{
    int j=0,k=-1;
    next[0]=-1;
    while(j<length(T))
    {
        if(k==-1 || T[j] == T[k])
        {
            ++j;
            ++k;
            if(T[j] != T[k])
            {
                next[j]=k;
            }else{
                next[j]=next[k];
            }
        }else{
            k=next[k];
        }
    }
}


int KMP2(char S[],char T[])
{
    int i=0,j=0;
    int next[5];
    GetNextVal(T,next);
    /*当S没有结束并且T也没有结束*/
    while(i<length(S) && j<length(T))
    {
        if(j==-1 ||  S[i]==T[j])
        {
            ++i;
            ++j;
        }
        else            /*j回溯*/
        {
            j=next[j];
        }
    }
    if(j>=length(T))   /*匹配成功,返回本次匹配的开始位置(不是下标)*/
    {
        return i-j+1;
    }else{
        return 0;
    }
}






0 0
原创粉丝点击