精华内容
下载资源
问答
  • 串的模式匹配,适用于大学数据结构上机实验课 可编译通过~~~没有问题
  • 串的模式匹配即子串定位是一种重要的串运算。设s和t是给定的两个串,在主串s中找到等于子串t的过程称为模式匹配,如果在s中找到等于t的子串,则称匹配成功,函数返回t在s中的首次出现的存储位置(或序号),否则匹配...
  • 主要介绍了C语言数据结构串的模式匹配的相关资料,需要的朋友可以参考下
  • 数据结构 c 字符串的模式匹配 简单算法以及KMP算法
  • 和大家一起分享数据结构串的模式匹配!写的很好!希望大家喜好!我们一起加油努力!
  • 串:串的模式匹配模式匹配的定义:实现代码: 模式匹配的定义: 实现代码: int Index(SString S,SString T,int pos){ int i = pos,j = 1; while(i <= S.length && j <= T.length){ if(S.ch[i] =...

    模式匹配的定义:

    在这里插入图片描述

    实现代码:

    int Index(SString S,SString T,int pos){
    	int i = pos,j = 1;
    	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;
    	}
    } 
    

    为什么是i - j + 2?
    在这里插入图片描述

    展开全文
  • 数据结构与算法实验指导 V2017 常熟理工学院 数据结构与算法实验指导与报告书 _2017-2018_学年 第_1_ ...1 数据结构与算法实验指导 V2017 实验四 串与模式匹配 实验目的 1掌握串的存储表示及基本操作 2掌握串的两种模式
  • 数据结构 串的模式匹配

    千次阅读 2020-05-05 16:58:00
    全部每周作业和视频思考题答案和解析 见浙江大学 数据结构 思考题+每周练习答案 题目一:若给定文本长度为 n,模式长度为 m,则库函数 strstr 最坏时间复杂度是: A. O(nm) B. O(n) C. O(m) D....

    全部每周作业和视频思考题答案和解析 见 浙江大学 数据结构 思考题+每周练习答案

    题目一:若给定文本长度为 n,模式长度为 m,则库函数 strstr 的最坏时间复杂度是:

    • A. O(nm)

    • B. O(n)

    • C. O(m)

    • D. O(n+m)

    乍看一眼就是O(nm),当然,我们可以想象到,除非m=1,否则不可能出现正好是n*m次比较的结果。

    题目二:对于 pattern = abcabcacab,最后 3 个字符的 match 值是多少?

    • A. 2, 3, 1

    • B. -1, 0, 1

    • C. -1, 0, -1

    • D. 5, 6, 4

    这个c所在的子串abcac和前面的配不上,而且又和一开始的a配不上,所以为-1,然后a和一开始的a配上了,为0,然后b为1。

    选B

    题目三:如果 match[j] 的值不是满足子序列条件的“最大”i,会出现什么问题?

    如果会出现问题,肯定就是没有匹配到呗。我们思考一下为什么会匹配不到:

    比如 abcabca ,match表示为:

    我觉得这个题目表达是有问题的,但是又不好描述,只能画个图来说说这个思考问题是想干嘛。如果match不取最大i的时候,就可能出现下面这种匹配:蓝色表示能被匹配上的字符子串

    在做匹配的时候,string的abcabca和pattern的abcabcac正好相互匹配,而下一个就不匹配了,所以这个时候a就变为了0。

    感觉这个思考题没什么意义???

    为什么不能直接用 pattern: abcabcacabb 的最后一个能匹配上的子串进行匹配而要用最大的 i 呢?比如这里的最后面的ab

    比如我们要进行匹配的子串是:abcabcacabab.....模式字串为abcabcacabb,如果用abca进行匹配,那么:

     

    展开全文
  • 数据结构 串的模式匹配算法BF、KMP

    千次阅读 2019-01-12 02:27:32
    串的模式匹配 朴素的模式匹配算法(BF(BruteForce)算法) BF的算法实现 算法分析 KMP模式匹配算法 字符串前缀后缀 最长公共前后缀 next数组 kmp算法实现 KMP算法的改进 ​nextval数组实现 串的模式匹配 ...

    目录

    串的模式匹配

    朴素的模式匹配算法(BF(Brute Force)算法)

    BF的算法实现

    算法分析

    KMP模式匹配算法

    字符串前缀后缀

    最长公共前后缀

    next数组

    kmp算法实现

    KMP算法的改进

    ​nextval数组实现


    串的模式匹配

    模式匹配是数据结构中字符串的一种基本运算,给定一个子串,要求在某个字符串中找出与该子串相同的所有子串,这就是模式匹配

    假设P是给定的子串,T是待查找的字符串,要求从T中找出与P相同的所有子串,这个问题成为模式匹配问题。P称为模式T称为目标。如果T中存在一个或多个模式为P的子串,就给出该子串在T中的位置,称为匹配成功;否则匹配失败。

    朴素的模式匹配算法(BF(Brute Force)算法)

    朴素模式匹配算法的基本思想是穷举法,即就是将目标串S的第一个字符与模式串P的第一个字符进行匹配,若相等,则继续比较S的第二个字符和P的第二个字符;若不相等,则比较S的第二个字符和P的第一个字符,依次比较下去,直到得出最后的匹配结果。

    Brute-Force的基本思想是:从主串S=“S(0) S1 ...S(n-1)”的第pos个字符开始与子串T=“T(0) T1 ...T(n-1)”的第一个字符比较,如果相等则继续比较后一个字符否则从主串的下一字符开始与子串T的第一个字符重新开始比较,以此类推。如果在主串S中存在与子串T相等的连续字符序列,则匹配成功,函数返回子串T中第一个字符在主串S中的位置;否则,函数返回-1。简单的说,就是对主串的每一个字符作为子串的开头,与要匹配的字符串进行匹配。对主串做大循环,每个字符开头做T的长度的小循环,直到匹配成功或全部遍历完成为止。

    假设我们要从主串S=“goodgoogle”中,找到T=“google”这个子串的位置。步骤如下:

    1、主串S的第一位开始,S与T的前三个字母都匹配成功,但S的第四个字母是d 而 T的是g。第一位匹配失败。如图所示,竖直连线表示相等,弯折线表示不等,如图所示:

    2、主串S第二位开始,主串S首字母为o,模式串T的首字母为g,匹配失败,如图所示:

    3、主串S第三位开始,主串S首字母为o,模式串T的首字母为g,匹配失败,如图所示:

    4、主串S第四位开始,主串S首字母为d,模式串T的首字母为g,匹配失败,如图所示:

    5、主串S第五位开始,S与T,6个字母全匹配,匹配成功,如图所示:

    BF的算法实现

    /*  
    函数 int BF(const char *s,const char *sub,int pos) 从目标s的首位位置开始模式匹配,  
    用模式sub匹配s,寻找首个sub子串并返回其下标位置。若整个匹配过程失败,返回-1。
    */
    
    int BF(const char *s,const char *sub,int pos)
    {
        int slen = strlen(s);     //目标的长度  
        int sublen = strlen(sub); //模式的长度   
    
        int i = pos;  //目标的下标变量   
        int j = 0;    //模式的下标变量  
        
        while(i < slen && j < sublen)
        {
            if(s[i] == sub[i])
            {
                i++;     //继续比较后续字符 
                j++;
            }
            else    //指针退回重新开始匹配
            {
                i = i - j + 1;   //i退回上次匹配首位的下一位
                j = 0;      //j退回子串的首位
            }
        }
        if(j >= sublen)
        {
            return i - j;
        }
        return -1;
    }

    算法分析

    若模式子串的长度是m,目标穿的长度是n,这时最坏的情况是每遍比较都在最后出现不等,即每遍最多比较m次,最多比较n-m+1遍,总的比较次数最多为m(n-m+1),因此朴素的模式匹配算法的时间复杂度为O(mn)。朴素的模式匹配算法中存在回溯,这影响到匹配算法的效率,因而朴素的模式匹配算法在实际应用中很少采用。在实际应用主要采用无回溯的匹配算法,KMP算法和BM算法均为无回溯的匹配算法。

    KMP模式匹配算法

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

    在学习KMP算法之前,我们先需要准备大量的前置知识。

    字符串前缀后缀

    何为前缀后缀?简单来说,将一个字符串在任意位置分开,得到的左边部分即为前缀,右边部分即为后缀。例如对于字符串"abcd",它的前缀有"a","ab","abc";后缀有"d","cd","bcd"。注意前后缀均不包括字符串本身

    最长公共前后缀

    对于一个字符串来说,它既有前缀,又有后缀,所谓的最长公共前后缀,即该字符串最长的相等的前缀和后缀。例如上面的字符串"abcd"就没有公共前后缀,更别提最长了,因为它的前后缀里就没有相等的;而字符串"abcab"就有一个最长的公共前后缀即"ab"。

    那么求最长公共前后缀到底有什么用呢?我们先来分析BF解法中的操作,若不匹配,主串的下一字符开始与子串T的第一个字符重新开始比较

    在kmp算法中,若是上述情况,为最后一个元素 D 失配,则D之前的元素都被成功匹配,D之前为AB,模式的首部两位也是AB,则接下来比较的是第三位 C (注意此时主串中的匹配字符位置不变,即无回溯,主串在匹配过程中一直在向前遍历)如下图

    我们看到 原串 中字符 与 D 失配后,直接将 C 与 原串中该字符进行比较,原因是 D 之前的 串的最长公共前后缀长度为 2,即 若D失配后,我们根据此最长公共前缀的值来确定下个需要匹配的字符,即为模式中的第三个字符,2号下标,这就是kmp的核心,避免了不必要的匹配,提高了匹配的效率。

    next数组

    next数组是kmp算法的核心,它表明了若模式中的某字符在主串中匹配失败后,下次需要匹配的模式中的字符。

    网上的博客中有很多next数组的版本,如严蔚敏《数据结构》中模式串从1号下标,开始为了清晰期间,本文在这里做如下规则约束:

    • 模式串从0号下标开始
    • next[0] = -1
    • next[1] = 0

    关于next数组的定义有数学方式,难于理解,接下来先讲解next数组的使用方法与求解方式,最后我们给出数学公式定义。

    例:对于模式 abcababcabc,它的next数组如下

    接下来我们分析 next[j] 的含义

    • next[0] = -1
    • next[1] = 0
    • next[2] = 0,表示若 c 匹配失败,下次匹配时从模式中下标为0的字符,即a,从头开始。
    • next[3]同上
    • next[4]  = 1,表示若4号下标 b 匹配失败,下次匹配时从模式中下标为1的字符,即b开始,因为4号下标失配,则之前的a已被匹配,恰好模式0号下标正好为a,则下次从0号下标后即1号下标进行匹配
    • next[5] = 2,表示若5号下标 a 匹配失败,下次匹配时从模式中下标为2的字符,即c开始,因为5号下标失配,则之前的ab已被匹配,恰好模式0、1号下标正好为ab,则下次从1号下标后即2号下标进行匹配
    • next[6] = 1,表示若6号下标 b 匹配失败,分析同next[4]
    • next[7] = 2,表示若7号下标 c 匹配失败,分析同next[5]
    • next[8] = 3,表示若8号下标 a 匹配失败,下次匹配时从模式中下标为3的字符,即a开始,因为8号下标失配,则之前的abc已被匹配,恰好模式0、1、2号下标正好为abc,则下次从2号下标后即3号下标进行匹配
    • next[9] = 4,表示若9号下标 b 匹配失败,下次匹配时从模式中下标为4的字符,即b开始,因为9号下标失配,则之前的abca已被匹配,恰好模式0、1、2、3号下标正好为abca,则下次从3号下标后即4号下标进行匹配
    • next[10] = 5,表示若10号下标 c 匹配失败,下次匹配时从模式中下标为5的字符,即a开始,因为10号下标失配,则之前的abcab已被匹配,恰好模式0、1、2、3、4号下标正好为abcab,则下次从4号下标后即5号下标进行匹配

    结论:next[i] 的值为 i 号下标之前的串 的 最长公共前后缀的值

    next数组的几个练习

    例1:

    例2:

    例3:

    例4:

    例5:

    例6:

    例7:

    next数组实现

    void GetNext(int *next,const char *sub)
    {
    	int lensub = strlen(sub);
    
    	next[0] = -1;
    	next[1] = 0;
    	int i = 2;
    	int k = 0;
    	while(i < lensub)
    	{
    		if((k == -1) || sub[k] == sub[i-1])
    		{
    			next[i++] = ++k;
    		}
    		else
    		{
    			k = next[k];
    		}
    	}
    }

    kmp算法实现

    KMP算法中每一次的匹配:

    • 主串的起始位置 = 上一轮匹配的失配位置;
    • 模式串的起始位置 = 失配位置的next值
    int KMP(const char *s,const char *sub,int pos)
    {
    	int lens = strlen(s);//n
    	int lensub =  strlen(sub);//m
    
    	int i = pos;//主串的pos
    	int j = 0;//子串
    	
    	int *next = (int *)malloc(sizeof(int) * lensub);
    	GetNext(next,sub);
    
    	while(i < lens && j < lensub)
    	{
    		if((j == -1) || s[i] == sub[j])
    		{
    			i++;
    			j++;
    		}
    		else
    		{
    			j = next[j];//与 BF算法的不同之处,失配后下次模式中开始匹配的位置为失配位置的next值
    		}
    	}
    
    	if(j >= lensub)
    	{
    		return i-j;
    	}
    	return -1;
    }

    KMP算法的改进

    对kmp算法的改进其实就是对next数组的改进因为next数组在某些情况下仍然是有缺陷的,不够高效

    例如在模式串 s =  ’aaaab’  和 主串 t = ’aaabaaaab’ 匹配时,当在 i=3(b) , j=3(a) 时,产生失配,由下图的next数组中指出还需进行 i=3,j=2;i=3,j=1;i=3,j=0这三次比较。但是我们发现这样的比较是没有意义的,因为s串中前四个字符都相等所以不需要逐个与主串中的第4个字符进行比较。

    所以此时我们应该考虑直接进行 i=4,j=0 的比较,这就是说,在我们求出next[j] = k时,而模式串中s[j] = s[k],则当匹配字符s[j]和t[i] 比较不等时,不需要再进行 s[k] 和 t[i]的比较,而是直接和 s[next[k]] 比较,换句话说就是如果存在 s[j] = s[k],那么next[j] = next[k]。

    求nextval数组值有两种方法,一种是不依赖next数组值直接用观察法求得,一种方法是根据next数组值进行推理

    nextval求解练习:



    nextval数组实现

    void GetNextVal(int *nextval,const char *sub)
    {
    	int lensub = strlen(sub);
    	int *next = (int *)malloc(sizeof(int) * lensub);
    	GetNext(next,sub);
    
    	for (int i = 0; i < lensub; i++)  // 将next数组全部写入nextval
    	{
    		nextval[i] = next[i];
    	}
    
    	int i = 1;
    
    	// 接下来我们将next数组中所有sub[next[i]] 与 sub[i]相等的i的nextval改为nextval[next[i]]
    	while (i < lensub)
    	{
    		if (sub[i] == sub[next[i]]) // 当sub[next[i]] 与 sub[i] 相等时,我们做以优化
    		{
    			nextval[i] = nextval[next[i]];  // 把nextval[next[i]] 的值 赋给 nextval[i]
    		}
    		i++;
    	}
    }

     

    展开全文
  • 子串在主串中的定位操作称为串的模式匹配,记为index(s,t,pos),即在主串s中,从第pos个字符开始查找与子串t第一次相等的位置。若查找成功,则返回子串t的第一个字符在主串中的位序,否则返回0。其中主串称为目标串...

    模式匹配

    子串在主串中的定位操作称为串的模式匹配,记为index(s,t,pos),即在主串s中,从第pos个字符开始查找与子串t第一次相等的位置。若查找成功,则返回子串t的第一个字符在主串中的位序,否则返回0。其中主串称为目标串,子串称为模式串

    Brute-Force算法

    基本思想

    从目标串的第pos个字符开始与模式串的第一个字符比较,若相等则继续逐个比较后续字符,否则从主串的第pos+1个字符重新和模式串进行比较。以此类推,若存在和模式串相等的子串,则匹配成功返回模式串t的第一个字符在目标串s中的位置;否则,匹配失败返回0。
    Brute-Force算法如下

    int index(string *s,string *t,int pos){
    int i,j;
    if(pos < 1 || pos > s->length || pos > s->length - t->length + 1){
    return 0;
    }//参数非法
    i = pos - 1;
    i = 0;
    while(i < s->length && j < t->length){
    	if(s->ch[i] == t->ch[j]){
    		i++;
    		j++;//继续匹配下一个字符
    	}else{
    		i = i - j + 1;
    		j = 0;//主串、子串指针回溯,重新开始下一次匹配
    }
    }
    if(j >= t->length){
    	return i - t->length + 1;//返回主串中已匹配子串的第i个字符的位序
    }else{
    	return 0;//匹配不成功
    }
    }
    

    该算法较简单且易于理解,但效率不高,因为目标串指针(i)的回溯消耗了大量时间。

    KMP算法

    讨论一般情况,设目标串s=“s0 s1 … sn-1”,模式串"t0 t1 … tm-1",当si != tj 时存在
    "t0 t1 … tk-1" = “tj-k tj-k+1 … tj-1”(0<k<j)
    则下一次比较可以直接从tk与si开始继续下一趟的匹配。若模式串中不存在子串
    "t0 t1 … tk-1" = “tj-k tj-k+1 … tj-1”(0<k<j),则下一次比较从t0开始与si继续下一趟匹配。由此可见,k的取值可以由模式串的构成直接得出,与目标串s没有关系。
    此时令next[j]=k,则next[j]表明当模式串中第j个字符与目标串中si“失配”时,在模式串中需重新和目标串字符si进行比较的字符位置。

    next[j]的实现(修正后)
    void getnext(string *t,int next[]){//由模式串t求出next值
    int j,k;
    j = 0;
    k = -1;
    next[0] = -1;
    while(j < t->length){
    	if(k == -1 || t->ch[j] == t->ch[k]){
    		if(t->ch[j] != t->ch[k){
    			next[j] = k;
    		}else{
    			next[j] = next[k];
    	}else{
    k = next[k];
    }
    }
    
    KMP算法实现
    int KMPindex(string *s,string *t,int pos){
    int next[INIZSIZE],i,j;
    getnext(t,next);
    i = pos - 1;
    j = 0;
    while(i < s->length && j < t->length){
    	if(j == -1 || s->ch[i] == t->ch[j]){
    	i++;
    	j++;
    	}else{
    	j = next[j];
    	}
    }
    if(j >= t->length){
    	return i - t->length + 1;
    }else{
    return 0;
    }
    }
    
    展开全文
  • 数据结构——串的模式匹配算法

    千次阅读 2017-05-10 18:11:09
    2、串的模式匹配算法  串的查找操作也称作串的模式匹配操作,模式匹配操作的具体含义是:在主串(也称作目标串)中,从位置start开始查找是否存在子串(也称作模式串),如在主串中查找到一个与模式串相同的子串,...
  • 数据结构第09讲_串的模式匹配与串的应用, 模式匹配的一种改进算法
  • 串的模式匹配写在前面1.头文件及类型定义2.串类型定义3.函数声明4.基本操作4.1 初始化串4.2 赋值操作4.3 朴素(简单)模式匹配算法1★★4.4 朴素(简单)模式匹配算法2★★4.5 求next数组★★★4.6 KMP算法★★★4.7 ...
  • 数据结构_串_串的模式匹配_KMP/BF
  • 参考资料:《数据结构(C语言版)严蔚敏著》 版权说明:未经作者允许,禁止转载。...模式匹配:在S中定位某个子串T操作称为模式匹配,其中S称为目标T称为模式。 匹配成功:在模式...
  • 本程序具体实现了《数据结构》课本 严蔚敏 吴伟民编著 清华大学出版社 串的模式匹配算法,并给出了模式串next数组的具体值。
  • 编程实现如下功能: 1、在实验六的基础上,实现串的Brute-Force模式匹配算法。 2、尝试实现串的KMP模式匹配算法。
  • 该文档描述了数据结构串的相关知识,朴素的模式匹配,KMP模式匹配,相关的概念,基本知识和代码的实现
  • 数据结构- 串的模式匹配算法 BF和 KMP算法
  • 转载自http://www.cnblogs.com/dolphin0520/ 十分感谢作者大大 KMP算法 KMP算法 在介绍KMP算法之前,先介绍一下BF算法。 一.BF算法 ... BF算法是普通的模式匹配算法,BF算法的思想就是将...
  • 串的模式匹配问题就是在串s中找到一个与串t相等的子串,通常将串s称为目标串,串t称为模式串,因此该问题被称为模式匹配问题。 Brute-Force算法与Knuth-Morris-Pratt算法都是解决串的模式匹配
  • 数据结构之字符串的模式匹配

    千次阅读 2015-08-25 21:49:40
    字符串的模式匹配问题: 一共有两种算法, 1.朴素模式匹配算法。 举例而言(寻找从S=”goodgoogle”中找到V=”google”这个子串):我们一般需要以下的步骤 (1).从主串的第一个字符开始,S与V中的字符逐一比较...
  • * 否则从s串的第二个字符起再重新和串t进行比较。以此类推,直至串t中每个字符依次和串s的一 * 个连续的字符序列相等,则称为模式匹配成功,此时串t的第一个字符在串s中的位置就是t在s中 * 的位置,否则模式...
  • 思路:将目标S第一个字符与模式串T第一个字符进行匹配,若相等,则继续比较S第二个字符和 T第二个字符;若不相等,则比较S第二个字符和T第一个字符,依次比较下去,直到得出最后的匹配结果。 代码...
  • 1、定义:子串的定位操作称为串的模式匹配。 比如:主串S=”goodgoogle”;子串T=”google”;找到子串T的位置就是一个匹配。 实现方法: 从主串第一位开始遍历,直到匹配成功或者遍历结束。 2、KMP模式匹配法:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,132
精华内容 852
关键字:

串的模式匹配数据结构

数据结构 订阅