[数据结构]程杰模式串匹配、KMP算法及其改进(代码)

[数据结构]模式匹配算法--KMP算法详解 KMP 阅读详情
#include "string.h"
#include "stdio.h"    
#include "stdlib.h"   
#include "io.h"  
#include "math.h"  
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100 /* 存储空间初始分配量 */

typedef int Status;     /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int ElemType;   /* ElemType类型根据实际情况而定,这里假设为int */

typedef char String[MAXSIZE+1]; /*  0号单元存放串的长度 */

/* 生成一个其值等于chars的串T */
Status StrAssign(String T,char *chars)
{ 
    int i;
    if(strlen(chars)>MAXSIZE)
        return ERROR;
    else
    {
        T[0]=strlen(chars);
        for(i=1;i<=T[0];i++)
            T[i]=*(chars+i-1);
        return OK;
    }
}

Status ClearString(String S)
{ 
    S[0]=0;/*  令串长为零 */
    return OK;
}

/*  输出字符串T。 */
void StrPrint(String T)
{ 
    int i;
    for(i=1;i<=T[0];i++)
        printf("%c",T[i]);
    printf("\n");
}

/*  输出Next数组值。 */
void NextPrint(int next[],int length)
{ 
    int i;
    for(i=1;i<=length;i++)
        printf("%d",next[i]);
    printf("\n");
}

/* 返回串的元素个数 */
int StrLength(String S)
{ 
    return S[0];
}

/* 朴素的模式匹配法 */
int Index(String S, String T, int pos) 
{
    int i = pos;    /* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
    int j = 1;              /* j用于子串T中当前位置下标值 */
    while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
    {
        if (S[i] == T[j])   /* 两字母相等则继续 */
        {
        	++i;
            ++j; 
        } 
        else                /* 指针后退重新开始匹配 */
        {  
            i = i-j+2;      /* i退回到上次匹配首位的下一位 */
            j = 1;          /* j退回到子串T的首位 */
        }      
    }
    if (j > T[0]) 
        return i-T[0];
    else 
        return 0;
}

/* 通过计算返回子串T的next数组。 */
void get_next(String T, int *next) 
{
    int i,j;
    i=1;
    j=0;
    next[1]=0;
    while (i<T[0])  /* 此处T[0]表示串T的长度 */
    {
        if(j==0 || T[i]== T[j])     /* T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 */
    	{
            ++i;  
            ++j;  
            next[i] = j;
        } 
        else 
            j= next[j]; /* 若字符不相同,则j值回溯 */
    }
}

/* 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。 */
/*  T非空,1≤pos≤StrLength(S)。 */
int Index_KMP(String S, String T, int pos) 
{
    int i = pos;        /* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
    int j = 1;          /* j用于子串T中当前位置下标值 */
    int next[255];      /* 定义一next数组 */
    get_next(T, next);  /* 对串T作分析,得到next数组 */
    while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
    {
        if (j==0 || S[i] == T[j])   /* 两字母相等则继续,与朴素算法增加了j=0判断 */
        {
            ++i;
            ++j; 
        } 
        else            /* 指针后退重新开始匹配 */
            j = next[j];/* j退回合适的位置,i值不变 */
    }
    if (j > T[0]) 
        return i-T[0];
    else 
        return 0;
}

/* 求模式串T的next函数修正值并存入数组nextval */
void get_nextval(String T, int *nextval) 
{
    int i,j;
    i=1;
    j=0;
    nextval[1]=0;
    while (i<T[0])  /* 此处T[0]表示串T的长度 */
    {
        if(j==0 || T[i]== T[j])     /* T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 */
    	{
            ++i;  
            ++j;  
            if (T[i]!=T[j])      /* 若当前字符与前缀字符不同 */
                nextval[i] = j; /* 则当前的j为nextval在i位置的值 */
            else 
                nextval[i] = nextval[j];    /* 如果与前缀字符相同,则将前缀字符的 */
                                            /* nextval值赋值给nextval在i位置的值 */
        } 
        else 
            j= nextval[j];          /* 若字符不相同,则j值回溯 */
    }
}

int Index_KMP1(String S, String T, int pos) 
{
    int i = pos;        /* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
    int j = 1;          /* j用于子串T中当前位置下标值 */
    int next[255];      /* 定义一next数组 */
    get_nextval(T, next);   /* 对串T作分析,得到next数组 */
    while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
    {
        if (j==0 || S[i] == T[j])   /* 两字母相等则继续,与朴素算法增加了j=0判断 */
        {
            ++i;
            ++j; 
        } 
        else            /* 指针后退重新开始匹配 */
            j = next[j];/* j退回合适的位置,i值不变 */
    }
    if (j > T[0]) 
        return i-T[0];
    else 
        return 0;
}

int main()
{
    int i,*p;
    String s1,s2;
    
    StrAssign(s1,"abcdex");
    printf("子串为: ");
    StrPrint(s1);
    i=StrLength(s1);
    p=(int*)malloc((i+1)*sizeof(int));
    get_next(s1,p); 
    printf("Next为: ");
    NextPrint(p,StrLength(s1));
    printf("\n");

    StrAssign(s1,"abcabx");
    printf("子串为: ");
    StrPrint(s1);
    i=StrLength(s1);
    p=(int*)malloc((i+1)*sizeof(int));
    get_next(s1,p); 
    printf("Next为: ");
    NextPrint(p,StrLength(s1));
    printf("\n");

    StrAssign(s1,"ababaaaba");
    printf("子串为: ");
    StrPrint(s1);
    i=StrLength(s1);
    p=(int*)malloc((i+1)*sizeof(int));
    get_next(s1,p); 
    printf("Next为: ");
    NextPrint(p,StrLength(s1));
    printf("\n");

    StrAssign(s1,"aaaaaaaab");
    printf("子串为: ");
    StrPrint(s1);
    i=StrLength(s1);
    p=(int*)malloc((i+1)*sizeof(int));
    get_next(s1,p); 
    printf("Next为: ");
    NextPrint(p,StrLength(s1));
    printf("\n");

    StrAssign(s1,"ababaaaba");
    printf("   子串为: ");
    StrPrint(s1);
    i=StrLength(s1);
    p=(int*)malloc((i+1)*sizeof(int));
    get_next(s1,p); 
    printf("   Next为: ");
    NextPrint(p,StrLength(s1));
    get_nextval(s1,p); 
    printf("NextVal为: ");
    NextPrint(p,StrLength(s1));
    printf("\n");

    StrAssign(s1,"aaaaaaaab");
    printf("   子串为: ");
    StrPrint(s1);
    i=StrLength(s1);
    p=(int*)malloc((i+1)*sizeof(int));
    get_next(s1,p); 
    printf("   Next为: ");
    NextPrint(p,StrLength(s1));
    get_nextval(s1,p); 
    printf("NextVal为: ");
    NextPrint(p,StrLength(s1));

    printf("\n");

    StrAssign(s1,"00000000000000000000000000000000000000000000000001");
    printf("主串为: ");
    StrPrint(s1);
    StrAssign(s2,"0000000001");
    printf("子串为: ");
    StrPrint(s2);
    printf("\n");
    printf("主串和子串在第%d个字符处首次匹配(朴素模式匹配算法)\n",Index(s1,s2,1));
    printf("主串和子串在第%d个字符处首次匹配(KMP算法) \n",Index_KMP(s1,s2,1));
    printf("主串和子串在第%d个字符处首次匹配(KMP改良算法) \n",Index_KMP1(s1,s2,1));

    return 0;
}

数据结构 —— 改进的KMP算法 KMP算法 如果我们要对下面的主串P和模式串P进行匹配 步骤一:i=3,j=3 模式串 “abab” 对应的 next 数组为-1 0 0 1(0 0 1 2整体右移一位,初值赋为-1),当模式串 P 和主串 S 进行匹配时,发现b跟c失配,于是模式串 P 右移 j - next[ j ] = 3 - 1 =2位。 步骤二:i=3,j=1 右移2位后,b又跟c失配。事实上,因为在上一步的匹配中,... 阅读详情

相关推荐

字符串模式匹配算法——KMP算法

字符串是一种常见的数据结构,它由一个字符序列组成,可以被视为字符的数组或列表。每个字符都有一个对应的索引位置,允许对字符串进行访问、修改和操作。对于字符串而言,寻找字符串中子串的位置是最重要的操作之一,查找子串位置的操作通常称为。

m0_73609199的博客 3732

KMP算法和KMP改进算法

KMP算法 1.应用: 模式匹配; 2.nextval向量的定义: 当模式串中的T[i]和源串匹配失败时,下一次必要的匹配比较是用T[nextval[i]]与源串当前字符比较;若模式串已不可能与当前位置形成匹配则计nextval[i]=-1; 3.nextval向量的计算 3.1 最大相同首真子串和尾真子串长度K[i]的计算 设k[0]=-1; 根据k[i-1]计算k[i]; 令k=k[i-1],若k=-1,则k[i]=0,否则若t[k]=t[i+1](模式串中元素...

weixin_61756086的博客 444

【数据结构】模式串匹配

【数据结构】模式串匹配 KMP及next数组详解

Obliviate的博客 6434

字符串匹配算法KPM实现-JAVA

参考这篇文章写了个JAVA的KPM算法实现 http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

xh19851011的博客 1269

数据结构与算法 | KMP算法及其改进算法的核心思路 (C语言实现)

kmp算法是子串配对的一种,并不是速度最快的,但是其算法思想非常巧妙。请允许我尝试用白话描述一下其思想,如果有什么不对的地方,恳请矫正。

峰峰的博客 2943

KMP算法求解next数组值(模式串从下标0开始或从下标1开始)以及求值后与主串的匹配过程

写在前面:博主是一位普普通通的19届二本大学生,平时最大的爱好就是听听歌,逛逛B站。博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事,做自己以后不会留有遗憾的事,做自己觉得有意义的事,不浪费这大好的青春年华。博主写博客目的是记录所学到的知识并方便自己复习,在记录知识的同时获得部分浏览量,得到更多人的认可,满足小小的成就感,同时在写博客的途中结交更多志同道合的朋友,让自己在技术的路上并不孤单。 目录: 1.模式串从下标1开始的next数组求.

记录博主学到的点滴 5496

KMP字符串匹配算法及KMP优化代码

博主链接 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。-----摘要搜狗百科...

Anoyer的博客 1941

【数据结构】朴素模式匹配 & KMP算法

💯KMP算法就是消除指针i的回溯,让i指针只进不退,而只移动模式串指针指向位置的方法,由于此时"$p_1...p_{k-1}$"和"$p_{j-k+1}..p_j$"都是相同的,所以这时候相当于将$j1$指针指向前缀,$j1$不断前移,$j2$指针指向后缀,$j2$不断后移(这里j1是主动指针,而j2相当于从动指针),因为只要保证他们一直为之前的公共前缀,就可以不用在意这$k'-1$长度的子串,这样主要考虑的就是要找到前缀中的一个值 $p_k'=p_j$

DAY I 的成长之路 2963

KMP模式匹配算法详解

0x01.关于KMP算法 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n)...

ATFWUS的博客 2万+

数据结构 - KMP算法(C语言实现)

一. 简单模式匹配算法  对某一个串中某子串定位的操作称为串的模式匹配。(注意:求出的是字串在主串中的起始位置)  简单模式匹配算法的思想是:主串与模式串(待定位的串)从第一个位置开始进行比较,如果相等则比较下一字符,如果不相等则使模式串从第一个字符和主串的第二个字符进行比较,以此类推。 int Str_index(Str str, Str substr){ //简单模式匹配算法 int i...

C橘子 3106

bf算法和kmp算法及改进的kmp

给定一个子串,要求找出某个字符串中该子串的第一次出现的位置,即实现各种模式匹配。本资源中含有bf算法,和kmp算法,以及改进后的kmp算法

模式串匹配的BF算法和KMP算法

KMP是三位大牛:D.E.Knuth、J.H.Morris和V.R.Pratt同时发现的。为了解决模式匹配问题,也即寻找模式串(子串)在主串中第一次出现的位置,若模式串在主串中不存在则返回-1。 简单的模式匹配算法(BF算法) 对于简单的模式匹配,也即暴力破解,我们的想法是:从左到右一个个匹配,如果这个过程中有某个字符不匹配,就跳回去,将模式串向右移动一位。 两个变量i和j分别记录主...

shimadear的博客 6164

机器人手眼标定快速精度验证方法

机器人手眼标定快速精度验证方法

laoli_的博客 1万+

【数据结构】串模式匹配及KMP算法详解——看不懂来砍我

本篇博客参考了以下几篇文章和视频: 参考1 参考2 武大MOOC 初学数据结构,第一次遇到了一根难啃的骨头——串的模式匹配算法(KMP),虽然网上关于KMP算法的介绍很多,但多半叙述不全面,推导不流畅。因此自己写了这篇博客,尽可能以因果关系呈现KMP算法。 本篇博客尽量以最通俗,详尽的语言解释KMP算法,全文干货,无废话。 KMP是用来干嘛的? 简而言之,KMP算法较好的解决了串的模式匹配问题,即判断模式串(t)是否是目标串(s)的子串,注意子串包含目标串本身,也包含空串。例如aaab是aaabaab

qq_45888298的博客 6712

AB SCIEX质谱数据分析实战:从PeakView入门到精通

质谱分析是现代生命科学和药物研发中不可或缺的核心技术,它通过测量离子的质荷比来鉴定和定量化合物。其基本原理是将样品离子化后,在电场和磁场中按质荷比分离,最终形成质谱图。这项技术的核心价值在于能够从复杂混合物中高灵敏度、高特异性地获取化合物的定性和定量信息,广泛应用于代谢组学、蛋白质组学、环境监测和药物分析等领域。在实际工作中,高效的数据处理平台至关重要。以AB SCIEX质谱仪生成的.wiff文件为例,其原始数据需要专业软件进行解析。PeakView软件正是这样一个综合平台,它集成了高级数据处理、谱图解析和

weixin_29053577的博客 306

Ansys Lumerical | 薄膜铌酸锂电光调制器的仿真与优化

本文详细介绍了使用Ansys Lumerical进行薄膜铌酸锂电光调制器仿真与优化的全流程。从基础原理到电学仿真、光学模拟技巧,再到设计优化实战经验,帮助工程师掌握这一先进光电器件的仿真方法。重点解析了薄膜铌酸锂的Pockels效应和Mach-Zehnder结构设计,并提供了常见问题排查指南和最新发展动态。

vulkan6gpu的博客 1196

数据结构面试常见问题之串的模式匹配(KMP算法)系列-大师改进

KMP算法的核心思想是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数。具体来说,KMP算法通过一个next数组记录模式串的部分匹配信息,当主串与模式串匹配失败时,可以根据next数组直接跳转到模式串中下一个可能匹配的位置,避免回溯。KMP算法是字符串匹配领域的重要算法,具有广泛的应用价值。KMP算法的核心思想是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数,从而提高匹配效率。😁热门专栏推荐想学习vue的可以看看这个java基础合集数据库合集redis合集nginx合集linux合集手写机制。

业精于勤,荒于嬉 1439

小白学电路之cadance搭建buffer电路

Buffer(缓冲器)是一种放大器或驱动电路,主要用于隔离输入和输出,以防止负载对前级电路造成干扰或影响。本文作者在电路方面是小白水平,目前正在学习,有不足之处欢迎指正。3.创建新的cellview,对此buffer进行仿真验证。2.创建buffer的symbol。电路中的V2的详细参数。

weixin_58051657的博客 1984

KMP(模式串匹配)算法详解【零基础教程+KMP优化】

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。 关于字符串匹配算法基本用这些算法解...

kuronekonano的博客 1992

SIC知识(8)--碳化硅的制备难点

6. 器件制造难点:碳化硅器件制造过程中的掺杂步骤需要在高温下完成,且需要采用高温离子注入的方式,这与传统硅基器件的扩散工艺不同。这些步骤需要精密的设备和严格的工艺控制,以确保器件的结构和功能。综上所述,碳化硅的制备难点相较于传统硅基器件主要在于更高的制备温度、更慢的生长速度、晶型控制的复杂性、后加工的难度、外延工艺的低效率以及器件制造的特殊要求和较高的成本。- **数据管理**:需要有效的数据管理系统来跟踪和记录生产过程中的每一个步骤,包括原料的批次、生长条件、加工参数等,以确保产品质量的可追溯性。

阿拉伯梳子的专栏 1595

Clion+platformIO开发ESP32时找不到lib文件中引入第三方库的头文件(头文件下有波浪线),实际编译是成功的解决方法

Clion+platformIO开发ESP引入第三方库文件编译器无法找到.h文件但编译成功

zs5218的博客 1852

数据结构 串模式匹配 KMP算法

【数据结构】 串 KMP算法实现 KMP算法应用于串的模式匹配中 普通模式匹配算法在进行匹配时需要频繁对主串指针进行回溯,KMP算法通过将模式向右滑动一段距离的方式避免了主串的回溯,同时降低了算法复杂度 ,由原来的O(n*m)变为O(n)。 KMP算法本身比较容易理解,就是对模式串本身的结构进行分析,在匹配过程中跳过一些不必要的步骤。 比如当模式串为ababc; 主串为ababdddd时; 匹...

欢乐佛的博客 3988

SAP-HR 模块 PPOSE 的详细信息标签页增强

步骤1:T-CODE : SE11 创建一个名为 HRI9106 的结构 命名:HRI + 91 + 两位数字。人事管理 - 组织管理 - 集成新信息类型 - 将信息类型添加为明细范围中的标签页。步骤6:SE51 查看 7000屏幕,修改屏幕属性 让其更美观。步骤3:T-CODE : SM30维护 T777I 表。步骤5:PPCI 新建 7000屏幕用于显示。标签页 IT 开头 + 信息类型 9106。步骤2:T-CODE : PPCI。步骤4:T-CODE : SPRO。

常回来看看呀!! 1627

408数据结构学习笔记——串、朴素模式匹配、kmp算法及其改进

1.串的定义 2.串的存储结构 3.朴素模式匹配 4.kmp算法 5.kmp算法的改进 6.王道课后题

JiangNan_1002的博客 2622

VMware16虚拟机:下载和安装教程

VMware16 虚拟机 下载和安装教程

MQ0522的博客 20万+

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

上一篇: [数据结构]程杰字符串的基本操作代码
下一篇: [数据结构]程杰 二叉树顺序结构实现_BiTreeArray
ilikeprograming
博客等级 码龄14年 46粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值