字符串及其匹配方法

一、字符串基本概念

 字符串是由零个或多个字符构成的有限序列,一般可表示为如下形式:"C1C2C3C4......Cn" (n>=0)

串中所含字符的个数n称为字符串的长度。当n=0时,字符串为空串。

字符串结束标识符:' \0 '

 

二、基本函数

求字符串的长度

int length(char str[] ){
    char*p=str;
    int len=0;
    while((*p)!='\0'){
        p++;len++;
    }
    return len;
}

 

 三、模式匹配——BF算法

基本思想

从主串T的第一个字符开始和模式串P的第一个字符进行比较,若相等,则继续比较两者的后续字符;否则,从主串的第二个字符开始和模式P的第一个字符进行比较,重复上述过程,直到P的字符串全部比较完,则说明匹配成功;或者T中的字符全部比较完,则说明匹配失败。

时间复杂度分析:

最好情况:不成功的匹配都发生在匹配串的第一个字符。

假设主串有n个字符,匹配串有m个字符,匹配成功发生在主串的第i个位置上(i从0开始)。则有i-1次不成功和1次成功,不成功中的匹配次数为i-1,成功的匹配次数为m。总共匹配次数=匹配失败花费次数+匹配成功花费次数=i-1+m。所有匹配成功的情况共有n-m+1种。将这n-m+1种情况的匹配次数加权求平均。即可得到时间复杂度为=O(n+m)

 最坏情况:不成功的匹配都发生在匹配串的最后一个字符。

同理,在i-1次不成功的匹配中共比较了 (i-1)*m次,第i次成功的匹配中比较了m次,总共比较了i*m次。经过加权求平均后得到时间复杂度=O(m*n)

代码实现

int BF_match(char str[],char s[]){
    int i,j,success;  //success是匹配成功的标志 
    i=j=success=0;    //i扫描正文,j扫描模式串 
    int str_len=length(str);
    int s_len=length(s);
    //主串剩余长度不小于匹配串 && 之前没匹配成功 
    while((i<=str_len-s_len) && (!success)){ 
        j=0;success=1; 
        //遍历模式串,遇到不相等字符将success置0,跳出当前while循环,然后i++,从主串的下个字符开始遍历 
        while((j<=s_len-1) && success){ 
            if(str[i+j]==s[j])
                j++;
            else
                success=0;
        }
        i++;
    }
    if(success)
        return i-1;
    else
        return -1;
}        

 

 四、KMP算法(快速模式匹配算法)

1.KMP算法基本概念

此算法可以在O(m+n)的时间量级上完成串的模式匹配算法。

通过引入next[]向量,使匹配串在与主串"失配"时,向右滑动更远的距离,减少模式串和主串不必要的匹配次数。从而提高效率。

基本步骤:

(1)求得模式串的next[]数组。

(2)令i,j初始值为0。

(3)若主串第i个字符等于模式串第j个字符,即Ti=Pj。i和j分别加1。

(4)否则,i不变,j=next[ j ]。

(5)若next[ j ]=-1,则从主串下一个位置重新与模式串第一个字符匹配。i++,j=0。

 

 2.next数组

next数组求法:

 

next数组代码:

void get_next(char str[],int next[]){
    int i=0,j=-1;
    next[0]=-1;
    int str_len=length(str);
    while(i<str_len){
        if(j==-1 || str[i]==str[j]){
            i++;j++;
            next[i]=j;
        }
        else
            j=next[j];
    }
    //打印next数组 
    for(i=0;i<str_len;i++)
        printf("%d ",next[i]);
} 

 

3.Kmp函数代码

int Kmp(char str[],char s[],int next[]){
    int i=0,j=0;
    int str_len=length(str);
    int s_len=length(s);
    while(i<str_len && j<s_len){ 
        if(j==-1 || str[i]==s[j]){ 
            i++;j++;
            printf("i=%d*j=%d\n",i,j);
        }
        else
            j=next[j];
    }
    if(j==s_len){
        if(s_len==0)  //模式串为空串,匹配成功 
            return -2;
        else          //正常匹配成功 
            return i-s_len;
    }
    else  //匹配失败 
        return -1;
} 

 

 

 (○` 3′○) 感谢观看,希望对你有帮助!

posted @ 2022-11-21 17:07  Mr_宋先生  阅读(316)  评论(0编辑  收藏  举报