数据结构——串

1、串

1.1、串的定长顺序存储

#define MAXLEN 255
typedef struct{
    char ch[MAXLEN];
    int length;
}SString;//静态数组实现(定长顺序存储)

方案二的缺点有char只有一个字节的大小只能存储0-255

 

1.2、串的链式存储

typedef struct{
    char *ch;
    int length;
}HString;//动态数组实现(堆分配存储)
HString S;
S.ch = (char *)malloc(MAXLEN * sizeof(char));//用完要手动free
S.length = 0;

 

1.3、串的基本操作

 

1.3.1 SubString(&Sub,S,pos,len)求子串

作用:用Sub返回串S的第pos个字符起长度len的子串

bool SubString(&Sub,S,pos,len)
{
    //子串范围越界
    if(pos+len-1 > S.length)
        retrun false;
    for(int i = pos; i<pos+len; i++)
        Sub.ch[i-pos+1] = S.ch[i];
    Sub.length = len;
    return true;
}

 

1.3.2 StrCompare(S,T):比较操作。

作用:若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。

int StrCompare(S,T){
    for(int i = 1; i<=S.length && i<T.length;i++){
        if(S.ch[i]!=T.ch[i])
            return S.ch[i]-T.ch[i];
    }
    //扫描过的所有字符都相同,则长度长的串更长
    return S.length-T.lengh;
}

 

1.3.3 Index(S,T):定位操作。

作用:若主串s中存在与串T值相同的子串,则返回它在主串S中第一次出现的位 置;否则函数值为0。

Int Index(SString S,SString T){
    int i =1;n = StrLength(S),m =StrLength(T);
    SString sub;//用于暂存子串
    while(i<=n-m+1)
    {
        SubString(sub,S,i,m);
        if(StrCompare(sub,T)!=0) ++i;
        else return i; //返回子串在主串中的位置
    }
    return 0;
}

 

2、串的模式匹配

2.1 朴素模式匹配算法

int Index(SSring S,SString T){
    int k=1;
    int i=k, j=1;
    while(i<=S.length && j<=T.length){
        if(S.ch[i]==T.ch[j]){
        ++i;
        ++j;//继续比较后继字符
    }else{
        k++;//检查下一个子串
        i= k;
        j=1;
    }
}
if(j>T.length)
    return k;
else
    return 0;
}

若模式串长度为m,主串长度为n,则

匹配成功的最好时间复杂度:O(m)

匹配失败的最好时间负责度:O(n-m+1)=O(n-m)≈O(n)

朴素模式匹配算法的缺点:当某些子串与模式串能部分匹配时,主串的扫描指针i经常回溯,导致时间开销增加

2.2 KMP算法

改进思路:主串指针不回溯,只有模式串指针回溯

Int Index_KMP(SString S,SString T,int next[])
{
    int i = 1,j=1;
    while(i<=S.length&&j<=T.length){
        if(j==0||S.ch[i]==T.ch[j]){
            ++i;
            ++j;    //继续比较后续的字符
        }
        else
            j = next[j];        //模式串向右移动
    }
    if(j>T.length)
        return i-T.length;      //匹配成功
    else
        return 0;
}

举例1

 

2.2.1 求模式串的next数组

next数组:当模式串的第j个字符匹配失败时,令模式串跳到next[j]再继续匹配

串的前缀:包含第一个字符,且不包含最后一个字符的子串

串的后缀:包含最后一个字符,且不包含第一个字符的子串

当第j个字符匹配失败,由前1~j-1个字符组成的串记为S,则:

next[i]=S的最长相等前后缀长度+1

特别地:next[1]=0、next[2]=1

举例1:

 

举例2:

 

//KMP算法
Int Index_KMP(SString S,SString T,int next[])
{
    int i = 1,j=1;
    int next[T.length+1]//O(m)
        get_next(T,next)
    while(i<=S.length&&j<=T.length){//O(n)
        if(j==0||S.ch[i]==T.ch[j]){
            ++i;    
            ++j;    //继续比较后续的字符
        }
        else
            j = next[j];        //模式串向右移动
    }
    if(j>T.length)
        return i-T.length;      //匹配成功
    else
        return 0;
}

KMP算法平均时间复杂度:O(m+n)

 

2.2.2 KMP算法的进一步优化

 

 

nextval数组的求法:

先算出next数组
先令nextval[1]=0
    for(int j = 2;j<=T.length;j++)
    {
        if(T.ch[next[j]]==T.ch[j])
            nextval[j]=nextval[next[j]];
        else
            nextval[j]=next[j];
	}
    

KMP算法优化:当子串和模式串不匹配时j=nextval[j];

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值