字符串匹配---KMP

原理:

随后再写

next数组的求法:

void getnext(){
    Next[0]=-1;
    int i=0,j=-1,len=strlen(mo);
    while(i<len){
        if(j==-1||mo[i]==mo[j]){Next[++i]=++j;}
        else
            j=Next[j];
    }
}

匹配过程:

int KMP(){//匹配过程
    int i=0,j=0,p=0,l1=strlen(str),l2=strlen(mo);
    while(i<l1){
        if(j==-1||str[i]==mo[j]){++i,++j;}
        else j=Next[j];
        if(j==l2)p++;//模式串匹配完了  p用来计数
    }
    return p;//p统计的是模式串在原串中出现了几次
}

 

模板:

#include<algorithm>
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int maxn=1e5;
int Next[maxn];
char str[maxn],mo[maxn];

//求next数组
void getnext(){
    Next[0]=-1;
    int i=0,j=-1,len=strlen(mo);
    while(i<len){
        if(j==-1||mo[i]==mo[j]){Next[++i]=++j;}
        else
            j=Next[j];
    }
//打印求出来的next数组的值
//    for(int i=0;i<=len;i++)
//        printf("%d ",Next[i]);
//    printf("\n");
}

//优化后的next数组求法
void getnext1(){
    Next[0]=-1;
    int i=0,j=-1,len=strlen(mo);
    while(i!=len){
        if(j==-1||mo[i]==mo[j]){
            ++i,++j;
            if(mo[i]!=mo[j])
               Next[i]=j;
            else
               Next[i]=Next[j];
        }
        else j=Next[j];
    }
//打印求出来的next数组的值
//    for(int i=0;i<=len;i++)
//        printf("%d ",Next[i]);
//    printf("\n");
}

int KMP(){//匹配过程
    int i=0,j=0,p=0,l1=strlen(str),l2=strlen(mo);
    while(i<l1){
        if(j==-1||str[i]==mo[j]){++i,++j;}
        else j=Next[j];
        if(j==l2)p++;//模式串匹配完了  p用来计数
    }
    return p;//p统计的是模式串在原串中出现了几次
}
int main(){
    gets(str);
    gets(mo);
    getnext();
    printf("%d",KMP());
}

例题 (模板题)(ac代码在文末)

hdu1711    Number Sequence    hdu1711

求模式串在原串中第一次出现的位置

 

hdu2087 剪花布条  hdu2087

求模式串在原串中出现了几次

ps:注意 这类型题目有两种意思

          1.  原串  aaaaaa   模式串 aa  出现了 5次

          2.  原串  aaaaaa  模式串 aa 出现了 3次(本题是这种情况)

对于不同的情况  要做不同的修改

代码

//hdu1711  求模式串在原串中第一次出现的位置


#include<algorithm>
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int maxn=1e6+7;
int Next[maxn];
int s[maxn],mo[maxn];
int l1,l2;
void getnext(){
    Next[0]=-1;
    int i=0,j=-1,len=l2;
    while(i<len){
        if(j==-1||mo[i]==mo[j]){Next[++i]=++j;}
        else
            j=Next[j];
    }
}
int KMP(){
    int i=0,j=0,p=0;
    while(i<l1){
        if(j==-1||s[i]==mo[j]){++i,++j;}
        else j=Next[j];
        if(j==l2)return i-j+1;
    }
    return -1;
}
int T,n,m;
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)scanf("%d",&s[i]);
        for(int i=0;i<m;i++)scanf("%d",&mo[i]);
        l1=n;l2=m;
        getnext();
        printf("%d\n",KMP());
    }
}

 

//hdu2087  模式串在原串中出现几次
#include<algorithm>
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int maxn=1e6+7;
int Next[maxn];
char s[maxn],mo[maxn];
int l1,l2;
void getnext(){
    Next[0]=-1;
    int i=0,j=-1,len=l2;
    while(i<len){
        if(j==-1||mo[i]==mo[j]){Next[++i]=++j;}
        else j=Next[j];
    }
}
int KMP(){
    int i=0,j=0,p=0;
    while(i<l1){
        if(j==-1||s[i]==mo[j]){++i,++j;}
        else j=Next[j];
        if(j==l2)p++,j=0;//出现一次  模式串就要回到初始位置
    }
    return p;
}
int T,n,m;
int main(){
    while(~scanf("%s",s)){
        if(s[0]=='#')return 0;
        scanf("%s",mo);
        l1=strlen(s);l2=strlen(mo);
        getnext();
        printf("%d\n",KMP());
    }
}

 

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/holly_Z_P_F/article/details/83957839
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞