(浙大-19-夏-数据结构)KMP算法剖析

数据结构 同时被 2 个专栏收录
97 篇文章 2 订阅
68 篇文章 2 订阅

KMP算法
是由D.E. Knuth、J.H.Morris和V.R. Pratt提出的,可在一个主文本字符串S内查找一个词W的出现位置。
该算法主要实现过程(右移):
在已经匹配的模式串子串中,找出最长的相同的前缀和后缀,然后移动使它们重叠。尽量跳过一些不必要的比较,提高模式匹配的效率。
在这里插入图片描述
在这里插入图片描述



例题:
给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出。如果找不到,则输出“Not Found”。
本题旨在测试各种不同的匹配算法在各种数据情况下的表现。各组测试数据特点如下:

数据0:小规模字符串,测试基本正确性;
数据1:随机数据,String 长度为 10​5​​,Pattern 长度为 10;
数据2:随机数据,String 长度为 10​5​​,Pattern 长度为 10​2​​;
数据3:随机数据,String 长度为 10​5​​,Pattern 长度为 10​3​​;
数据4:随机数据,String 长度为 10​5​​,Pattern 长度为 10​4​​;
数据5:String 长度为 10​6​​,Pattern 长度为 10​5​​;测试尾字符不匹配的情形;
数据6:String 长度为 10​6​​,Pattern 长度为 10​5​​;测试首字符不匹配的情形。

输入格式:
输入第一行给出 String,为由英文字母组成的、长度不超过 10​6​​ 的字符串。第二行给出一个正整数 N(≤10),为待匹配的模式串的个数。随后 N 行,每行给出一个 Pattern,为由英文字母组成的、长度不超过 10​5​​ 的字符串。每个字符串都非空,以回车结束。

输出格式:
对每个 Pattern,按照题面要求输出匹配结果。

输入样例:
abcabcabcabcacabxy
3
abcabcacab
cabcabcd
abcabcabcabcacabxyz

输出样例:
abcabcacabxy
Not Found
Not Found

下面代码是该题稍作改动即可

#include<Stdio.h>
#include<stdlib.h>
#include<string.h>
#define Notfound -1
int KMP(char string[],char pattern[]);//KMP算法实现
void BuildMatch(char pattern[],int match[]);//match计算 
int main()
{
    char string[] = "This is a simple example.";
    char pattern[] = "simple";
    int p = KMP(string,pattern);//KMP算法实现
    if(p == Notfound)
        printf("Not found.\n");
    else 
        printf("%s\n",string + p);
    return 0;
} 
int KMP(char string[],char pattern[]) //T = O(n+m+Tm)
{
    int n = strlen(string);//计算位数 
    int m = strlen(pattern);
    int s,p, *match;//匹配数组 
    if(n < m)
        return Notfound;
    match = (int *)malloc(sizeof(int)*m);//申请空间 
    BuildMatch(pattern,match);//创建匹配数组 
    s = 0;
    p = 0;
    while( s < n && p < m)
    {
        if(string[s] == pattern[p])//相等 
        {
            s++;
            p++;
        }
        else if(p > 0)
            p = match[p - 1] + 1;
        else//第一个字母不相等 
            s++;
    }
    return ( p == m ) ? (s - m) : Notfound;//找到该数时,返回match[j]地址;未找到时,返回-1       
}
void BuildMatch(char pattern[],int match[])
{
    int i,j;
    int m = strlen(pattern);//计算位数 
    match[0] = -1; 
    for(j = 1;j <= m - 1;j++)
    {
        i = match[j - 1];
        while( (i >= 0) && pattern[i+1] != pattern[j] )//不相等时 
            i = match[i];
        if(pattern[i+1] == pattern[j])//相等时 
            match[j] = i + 1;
        else
            match[j] = -1;    
    }
    return ;     
}

推荐一个比较好的博文点击了解

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值