串的定义 存储结构 操作 简单模式匹配 KMP算法 C语言实现

串的定义

  • 串是由零个或多个字符组成的有限序列
  • 串中的字符个数n为串的长度
  • 字符在串中的位置一般情况下是从1开始数(位序)

串的存储结构

  1. 顺序存储

    #define MAXLEN 255
    typedef struct{
        char ch[MAXLEN];
        int length;
    }SString
    

    这种方式直接分配一个固定长度的存储区,销毁时系统会自动回收

  2. 堆分配存储(动态分配)

    仍然是一组地址连续的存储单元存放串值,但是存储空间是动态分配得到的

    typedef struct{
        char *ch;//按串长分配存储区,ch指向串的基地址
        int length;
    }HString
        
    //动态分配
    S.ch=(char *)malloc(MAXLEN*sizeof(char));
    

    在堆中的存储,用malloc()申请的空间,需要手动free()释放

  3. 块链存储

    用链表方式存储字符串值

    一个结点存放一个字符时存储密度低,可以存放多个字符

操作

  1. StrAssign(&T,chars):赋值操作,把串T赋值为chars
  2. StrCompare(S,T)S>T,则返回值>0S=T,则返回值=0;若S<T,则返回值<0
  3. StrLength(S):求串长
  4. SubString(&Sub,S,pos,len):求子串,用Sub返回串S的第pos个字符起长度为len的子串
  5. Index(S,T):定位操作,返回子串T在主串S中首次出现的位置
  6. ClearString(&S)S串清空
  7. DestroyString(&S):销毁,归还空间

简单模式匹配(朴素模式匹配)

子串的定位操作通常叫做模式匹配

算法思想:将主串中与模式串长度相同的子串搞出来,挨个与模式串对比,当子串与模式串某个对应字符不匹配时,就立即放弃当前子串,转而检索下一个子串

最坏时间复杂度:O(mn)

//朴素模式匹配算法
int Index(SString S,SString T){
    int k;//标记主串每次开始比较的位置
    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;
        }
}

主串多次回溯导致算法效率低

KMP算法

解决了主串回溯的问题

  1. 字符串前缀:除最后一个字符之外,所有头部子串
  2. 字符串后缀:除第一个字符之外,所有尾部子串
  3. 部分匹配值则为字符串的前缀和后缀的最长相等前后缀长度

ababa:前缀{a,ab,aba,abab},后缀{a,ba,aba,baba},最长相等前后缀长度为 3

next数组求法(串的位序从1开始)

当第 j 个字符匹配失败,由前 1j-1个字符组成的串记为S,则next[j]等于S的最长相等前后缀长度 +1

  • next[1]=0;模式串的第一个字符失配时
  • next[2]=1;

当串的位序从0开始,next[0]=-1

next[j]数组含义

在子串的第j个字符与主串发生失配时,则跳到子串的next[j]位置重新与主串当前位置进行比较

nextval[j]数组

如果出现了Pj=Pnext[j]时,连续失配,导致比较没有意义

解决办法:next[j]修正为next[next[j]],递归

ababaaababaa

编号123456789101112
Sababaaababaa
next011234223456
nextval010104210104
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值