数据结构之串的模式匹配(C语言实现)
来源:互联网 发布:怎样加入淘宝 编辑:程序博客网 时间:2024/05/21 23:09
一、暴力匹配算法(BF)
BF全称为Brute-Force,最简单直观的模式匹配算法。
1.算法思想
两个字符串进行匹配时,一个主串和一个模式串,就是按照我们最容易想到的算法来进行匹配。用两个变量i,j分别记录主串和模式串的匹配位置,如果两者在某个字符不匹配,则将记录主串匹配位置的变量i回退到匹配前i的位置的后一个位置,将j回头到模式串的第一个字符位置;如果i和j指向的主串和模式串字符匹配,则将两者同时向后走一个位置,继续比较;最后,如果j的位置已经走过了模式串的所有字符,则说明此时匹配成功。这个算法很简单,也容易理解,下面直接给出代码。
2.代码实现
#include<stdio.h>#include <string.h>int BF(const char *MainStr, const char *PatternStr){ int i = 0; //主串的匹配起始位置 int j = 0; //模式串的匹配起始位置 int iMainLen = strlen(MainStr); //主串长度 int iPatLen = strlen(PatternStr); //模式串长度 while (i < iMainLen && j < iPatLen) { if (MainStr[i] == PatternStr[j]) { ++i; //当前字符匹配成功,两者均往后走一个位置 ++j; } else { i = i - j + 1; //每次未匹配成功时i回退到原来i的后一位置 j = 0; //模式串每次未匹配成功时回退到0位置 } } if (j >= iPatLen) //条件满足说明j走过了模式串的所有字符 { return i - j; } return -1;}int main(void){ const char *MainStr = "abcdabddabc"; const char *PatternStr = "dabc"; int iPos = BF(MainStr, PatternStr); printf("iPos = %d\n", iPos); return 0;}
二、KMP算法
KMP算法的高明之处在于当主串和模式串在某个字符不匹配时,指示主串匹配位置的变量不需要回退,而直接回退指示模式串匹配位置的变量,而且该变量回退时也不需要像BF算法中回退到起始位置,而是基于原来已匹配过的结果来回退。关于KMP算法推导的过程很多博客中都有,而且很多书上也讲的很清楚,大家可以参考严奶奶的《数据结构》,里面有很清楚的推导,我就不写推导过程了。下面就我在理解KMP算法中遇到的问题加以说明,并给出KMP算法的实现代码。
问题1.next数组的本质
找到匹配成功部分的两个尽可能长的相等的真子串,一个子串以0下标开始,另一个真子串以j-1下标结尾。(这里的j表示模式串的第j个位置,从0开始计数)
问题2.next[j]=k的含义
next [j] = k,代表j 之前的字符串中有最大长度为k 的相同前缀后缀
问题3.解释next[0]=-1,next[1]=0
假设i指示主串的当前匹配位置,j指示模式串的当前匹配位置。从问题2可以知道next[0]=-1的含义就是当模式串和主串的第一个字符不匹配时,应该回退到-1这个位置,但是我们的数组下标最小为0,此时已经越界了。但是我们知道下一次匹配的情况,那就是主串的匹配位置往后走一个(即i+1位置),继续和模式串的0号位置匹配,所以此时应该将模式串的匹配位置也向后走一个(即从-1加1为0,从0号位置开始匹配,便于写代码)。同理next[1]=0,这个更容易理解,它表示的含义是当模式串的1号位置和主串不匹配时,模式串应该回退到0号位置进行匹配,这是理所当然的做法,也是退到无路可退。
问题4.解释if(j==-1 || sub[j] ==s[i])中j==-1这个条件
当j为-1时,说明此时模式串的第一个字符和主串不匹配,此时模式串第一个字符应该和主串的下一个字符继续比较,即应该要sub[0]和s[i+1]比较,这两种状态切换也是i++和j++的一个过程,所以可以将两者合在一起来写。
代码实现
#include<stdio.h>#include <string.h>#include <stdlib.h>void GetNext(const char *PatternStr, int *next){ int i = 1; int j = 0; next[0] = -1; next[1] = 0; int iPatLen = strlen(PatternStr); while (i < iPatLen) { if (j == -1 || PatternStr[i] == PatternStr[j]) { ++i; ++j; next[i] = j; } else { j = next[j]; } }}int KMP(const char *MainStr, const char *PatternStr){ int i = 0; int j = 0; int iMainLen = strlen(MainStr); //主串长度 int iPatLen = strlen(PatternStr); //模式串长度 int *next = (int*)malloc(sizeof(int) * iPatLen); GetNext(PatternStr, next); while (i < iMainLen && j < iPatLen) { if (j == -1 || MainStr[i] == PatternStr[j]) { ++i; ++j; } else { j = next[j]; } } if (j >= iPatLen) { return i - j; } return -1;}int main(void){ const char *MainStr = "abcdabddabc"; const char *PatternStr = "dabc"; int iPos = KMP(MainStr, PatternStr); printf("iPos = %d\n", iPos); return 0;}
在最后给出一点提醒,大家仔细看KMP()和GetNext()这两个函数,可以发现其实两者很相似,想想为什么,可以更好帮助你理解KMP算法。
阅读全文
0 0
- 数据结构之串的模式匹配(C语言实现)
- 数据结构c语言实现字符串定位(模式匹配)
- 数据结构之---C语言实现括号匹配(栈实现)
- 数据结构(C语言)读书笔记6:栈的应用之括号匹配的C代码实现
- 用c语言实现数据结构中的几个经典程序:串的模式匹配
- 用c语言实现数据结构中的几个经典程序:串的模式匹配
- C语言数据结构KMP算法实现模式串主串匹配(数据结构第三次试验)
- 数据结构之串的KMP模式匹配算法的实现
- C语言实现串的基本模式匹配
- 经典算法研究:模式匹配(子串匹配)之 KMP 算法(C语言实现版)
- 经典算法研究:模式匹配(子串匹配)之 BM 算法(C语言实现版)初版
- 数据结构 C语言 模式匹配 文件读取
- 数据结构之队列的实现(c语言)
- 数据结构之栈的c语言实现
- C语言实现的数据结构之------哈希表
- 数据结构之单链表的C语言实现
- 数据结构之双链表的C语言实现
- 数据结构之---C语言实现串的顺序存储
- 再谈java乱码:GBK和UTF-8互转尾部乱码问题分析
- python_week2_homework
- Java中文转拼音 直接获取首字母 用于字典排序 手机通讯录
- 微信小程序开发之五星评分
- 算法系列——和为S的连续正数序列
- 数据结构之串的模式匹配(C语言实现)
- 蓝牙语音功能的实现
- alarm()函数 SIGALRM信号的使用
- 设计模式的应用场景(12)--享元模式
- 常用自定义的内容
- 论算法性能的重要性
- 欢迎使用CSDN-markdown编辑器
- 不同领域的人们是怎样使用思维导图的(上)
- 数据结构之数组(C语言实现)