串模式匹配--KMP和BF

1、暴力匹配算法BF

假设现在我们面临这样一个问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢?

    如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有:

  • 如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符;
  • 如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯,j 被置为0。
    理清楚了暴力匹配算法的流程及内在的逻辑,咱们可以写出暴力匹配的代码,如下:
int ViolentMatch(char* s, char* p)  
{  
    int sLen = strlen(s);  
    int pLen = strlen(p);  
  
    int i = 0;  
    int j = 0;  
    while (i < sLen && j < pLen)  
    {  
        if (s[i] == p[j])  
        {  
            //①如果当前字符匹配成功(即S[i] == P[j]),则i++,j++      
            i++;  
            j++;  
        }  
        else  
        {  
            //②如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0      
            i = i - j + 1;  
            j = 0;  
        }  
    }  
    //匹配成功,返回模式串p在文本串s中的位置,否则返回-1  
    if (j == pLen)  
        return i - j;  
    else  
        return -1;  
}  

2、KMP算法

KMP算法引入了一个F数组(在很多文章中会称为next,但笔者更习惯用F,这更方便表达),F[i]表示的是前i的字符组成的这个子串最长的相同前缀后缀的长度!
怎么理解呢?
例如字符串aababaaba的相同前缀后缀有a和aaba,那么其中最长的就是aaba。

1.本文中,所有的字符串从0开始编号
2.本文中,F数组(即其他文章中的next),F[i]表示0~i的字符串的最长相同前缀后缀的长度。

模板:

s是模式串,t是主串

//next[i]表示和模式串第i位匹配失败时,再去和模式串第next[i]位匹配
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char s[100005],t[1000005];
int tot,nxt[1000005];
void kmp_pre(){
int i,j;
int len=strlen(s);
j=nxt[0]=-1;i=0;
while(i<len){
while(j!=-1 && s[i]!=s[j]) j=nxt[j];
nxt[++i]=++j;
}
}
void kmp(){
int i,j,ans;
int m=strlen(s);
int n=strlen(t);
i=j=ans=0;
while(i<n){
while(j!=-1 && t[i]!=s[j]) j=nxt[j];
++i,++j;//这个是在匹配的时候
if(j==m){
ans++;//ans是有几个匹配的。
j=nxt[j];
}
}
printf("%d\n",ans);
}
int main(){
int tt;
scanf("%d",&tt);
while(tt--){
memset(nxt,0,sizeof nxt);
scanf("%s%s",s,t);
kmp_pre();
kmp();
}
}

https://blog.csdn.net/f1033774377/article/details/82556438  一个能看的懂得教程

猜你喜欢

转载自www.cnblogs.com/h694879357/p/12293564.html