算法案例分析—字符串模式匹配算法
hello!大家好哇,我是灰小猿,一个超会写bug的沙雕程序猿!
今天来和大家分享一个关于字符串比较的模式匹配算法,在数据结构中对字符串的相关操作中,对子串的定位操作通常称为串的模式匹配,同样他也是各种串处理中最重要的操作之一,同时子串也称为模式串,关于主串和模式串的匹配算法常用的主要有两种:朴素的模式匹配算法和KMP算法(改进的模式匹配算法),接下来将分别对这两种算法进行分析。
一、朴素的模式匹配算法
朴素的模式匹配算法也被称为布鲁特—福斯算法,其基本思想是:从主串的第一个字符起与模式串的第一个字符相比较,若相等,则逐一对之后的字符进行比较,否则从主串的第二个字符与模式串的第一个字符重新比较,直到模式串中的每一个字符依次与主串中连续的字符序列相匹配为止,这时就称为匹配成功,如果不能在主串中找到与模式串相匹配的内容,则称为匹配失败。
接下来举一个例子,以字符数组存储字符串,实现朴素的模式匹配算法。
//传入主串s和模式串t,同时设定从主串中开始匹配的位置pos
int index(char s[],char t[],int pos) {
int i,j,slen,tlen;
i = pos;
j = 0;
slen = s.length; //获取到主串的长度
tlen = t.length; //获取到模式串的长度
while (i<slen && j<tlen) {
if (s[i] == t[j]) {
i++;
j++;
}
else {
i = i-j+1;
j=0;
}
}
if (j>=tlen) {
return i-tlen;
}
return 1;
}
二、KMP算法(改进的模式匹配算法)
KMP算法是上一个算法的改进,相比于朴素的模式匹配算法,KMP算法在进行主串和模式串的匹配过程中,每当匹配过程中出现相比较的字符不相等时,不需要回退主串的字符位置指针,而是利用已经得到的“部分匹配”结果将模式串向右“滑动”尽可能远的距离,再继续进行比较。
设模式串为“P0...P(m-1)”,KMP匹配算法的思想是:当模式串中的字符Pj与主串中相应的字符Si不相等时,因其前j个字符(“P0...P(j-1)”)已经获得了成功的匹配,所以若模式串中的“P0...P(k-1)”与“P(j-k)...P(j-1)”相同,这时可令P0与Si相比较,从而使i无需回退。
在KMP算法中,依据模式串的next函数值可以实现子串的滑动,若令next[j]=k,则next[j]表示当模式串中的Pj与主串中相应的字符不相等时,令模式串的Pnext[j]与主串的相应字符进行比较,
关于next函数有如下的定义:
以下是求模式串的next函数的程序:
//求模式串p的next函数值,并存入数组next中
void Get_next(char *p,int next[])
{
int i,j,slen;
slen = strlen(p); //获取到模式串的长度
i=0;
while (i<slen) {
if (j==-1||p[i]==p[j]) {
++i;
++j;
next[i] = j;
} else {
j = next[j];
}
}
}
在获取到的next函数后,
在KMP模式匹配算法中,设模式串的第一个字符下标为0,则KMP算法如下:
/*利用模式串p的next函数,求p在主串s中从第pos个字符开始的位置*/
/*若匹配成功,返回模式串在主串的位置下标,否则返回-1 */
int Index_KMP(char *s,char *p,int pos,int next[])
{
int i,j,slen,plen;
i=pos-1;
j=-1;
slen = strlen(s); //求主串的长度
plen = strlen(p); //求模式串的长度
while (i<slen && j<plen) {
if (j==-1||s[i]==p[j]) {
++i;
++j;
} else {
j=next[j];
}
}
if (j>=plen) {
return i-plen;
}
else {
return -1
}
}
关于字符串模式匹配算法就分享到这里,有不足的地方还希望各位大佬一起指正,
觉得不错记得点赞关注哟!
大灰狼陪你一起进步!
- Python 装饰器(Decorator)
- linux学习第三十七篇:安装PHP5,安装PHP7
- linux学习第三十八篇: Apache和PHP结合,Apache默认虚拟主机
- Python lambda表达式
- Python的闭包(Closure)与惰性计算(Lazy Evaluation)
- linux学习第三十九篇:Apache用户认证,域名跳转,Apache访问日志
- Python sorted()函数
- Python filter()函数
- Python reduce()函数
- Python map()函数
- Python iterator迭代器
- How To Implement The Decision Tree Algorithm From Scratch In Python (从零开始在Python中实现决策树算法)
- 『教程』微信小程序webview的使用
- How to Save an ARIMA Time Series Forecasting Model in Python (如何在Python中保存ARIMA时间序列预测模型)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- java线程池(六):ForkJoinPool源码分析之二(WorkQueue源码)
- Codeforces Round #605 (Div. 3) D. Remove One Element
- 用python爬虫,pyinstaller写一个属于自己的彩虹屁生成器!
- 2020牛客寒假算法基础集训营4 C 子段乘积
- Callable and Future in Java(java中的Callable和Future)
- Java类 初步学习
- Gephi可视化拓扑图简单实战
- python连接到SQList数据库以及简单操作
- 在markdown编辑器使用html绘制表格
- 循环不变式:算法中基础概念的明晰
- Codeforces Round #615 (Div. 3)B. Collecting Packages
- 七大设计原则、单一职责原则
- JSP 基本凉凉,学妹不知道他是啥
- Codeforces Round #615 (Div. 3)C. Product of Three Numbers
- Codeforces Round #622 (Div. 2) A.Fast Food Restaurant