大数据最新【王道数据结构】第四章 串 KMP算法_王道kmp

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


**基本操作的实现**



#define MAXLEN 255

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

// 1. 求子串
bool SubString(SString &Sub, SString S, int pos, int len){
//子串范围越界
if (pos+len-1 > S.length)
return false;

for (int i=pos; i<pos+len; i++)
    Sub.cn[i-pos+1] = S.ch[i];

Sub.length = len;

return true;

}

// 2. 比较两个串的大小
int StrCompare(SString S, SString T){
for (int i; 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.length;
}

// 3. 定位操作
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;            //S中不存在与T相等的子串

}


### 4、串的模式匹配


**模式匹配**:子串的定位操作称为串的模式,它求的是子串(常称模式串)在主串中的位置。


朴素模式匹配算法



> 
> 朴素模式匹配算法(简单模式匹配算法) 思想:
> 
> 
> * 将主串中与模式串长度相同的子串搞出来,挨个与模式串对比当子串与模式串某个对应字符不匹配时,就立即放弃当前子串,转而检索下一个子串。
> * 若模式串长度为m,主串长度为n,则直到匹配成功/匹配失败最多需要(n-m+1)\*m 次比较最坏时间复杂度: 0(nm)
> * 最坏情况:每个子串的前m-1个字符都和模式串匹配,只有第m个字符不匹配。
> * 比较好的情况:每个子串的第1个字符就与模式串不匹配
> 
> 
> 



int Index(SString S, SString T){
int i=1; //扫描主串S
int j=1; //扫描模式串T
while(i<=S.length && j<=T.length){
if(S.ch[i] == T.ch[j]){
++i;
++j; //继续比较后继字符
}
else{
i = i-j+2;
j=1; //指针后退重新开始匹配
}
}
if(j>T.length)
return i-T.length;
else
return 0;
}



> 
> 时间复杂度
> 
> 
> * 主串长度为n,模式串长度为m
> * 最多比较n-m+1个子串
> * 最坏时间复杂度 = O(nm)
> * 每个子串都要对比m个字符(对比到最后一个字符才匹配不上),共要对比n-m+1个子串,复杂度 = O((n-m+1)m) = O(nm - m^2 + m) = O(nm)(n远远大于m)
> * 最好时间复杂度 = O(n)
> * 每个子串的第一个字符就匹配失败,共要对比n-m+1个子串,复杂度 = O(n-m+1) = O(n)
> 
> 
> 


### 5、KMP算法


**算法思想**


* 不匹配的字符之前,⼀定是和模式串⼀致的,即如果j=k才发现匹配失败,说明1~k-1都匹配成功。可以利用部分匹配成功的字符,确定模式串指针应该回溯到哪,主串指针是否要加1


KMP算法的时间复杂度为O ( m + n ) O(m+n)O(m+n),而一般情形下普通模式匹配算法实际执行时间近似也为O ( m + n ) O(m+n)O(m+n),因此至今仍被采用。KMP仅在主串与模式串有很多部分匹配时才显得比普通算法快得多,其主要优点是主串不回溯。


整体上与简单匹配算法类似


* 当匹配过程产生**失配**时,指向主串的指针i不变,指向模式串的指针j退回到next[j]的位置并重新进行比较;
* 当j为0时,i与j同时加1;
* 若主串的第i个位置和模式串的第一个字符不等,从主串的第i+1个位置开始匹配。



int indexKMP(String S, String T, int next[]){ // 主串,模式串,next数组
int i = 1, j = 1;
while(i <= S.length && j <= T.length){
if(j==0 || S.ch[i] == T.ch[j]){ // j等于0或未适配,两指针均向后移动
i++;
j++;
}else{ // 指针失配且j不等于0,i不移动,j移动到next[j]处
j = next[j];
}
if(j > T.length)
return i - T.length; // 匹配成功
else
return 0;
}


* 朴素模式匹配算法的缺点:当某些子串与模式串能部分匹配时,主串的扫描指针 i 经常回溯,导致时间开销增加。!最坏时间复杂度O(nm)
* KMP算法:当子串和模式串不匹配时,主串指针i不回溯,模式串指针j=next[j]算法平均时间复杂度: o(n+m)


![img](https://img-blog.csdnimg.cn/img_convert/a081086e2ea745d59fa6cb25702e3978.png)
![img](https://img-blog.csdnimg.cn/img_convert/2d7e744334274b6f8cd40031b2567ef4.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值