字符串匹配算法KMP算法
数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法。
朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多多余的不符合的匹配做了冗余的比较。假设源字符串长n,字串长m 该算法最差时间复杂度为 m*(n-m+1),记为O(n*m);这里不做过多解释朴素匹配算法。
KMP算法:
kmp算法不是在源字符串中下手,他是从字串下手,比如我要在源字符串(acabaabaabcacaabc)中匹配一个字符串字串(abaabcac),那么从字串abaabcac下手,分析字串时,需要借助于一个数组存储字串中存在头字串和尾字串对称相等的子串长度,例如 abaabcac,
a next[0] = -1,规定第一个字符对应的next值为-1;
ab next[1] = 0; 因为针对字符b而言,其前边字符串a 不存在头字串和尾字串对称,所以为0;
aba next[2]=0 ; 因为针对子串 ab ,不存在头字串和尾字串对称,所以为0;
abaa next[3]=1 ; 因为针对子串aba ,存在 头子串a和尾子串a对称相等,其长度为1,所以为1;
abaab next[4]=1; 因为针对子串abaa ,存在 头子串a和尾子串a对称相等,其长度为1,所以为1;
abaabc next[5]=2; 因为针对子串abaab ,存在 头子串ab和尾子串ab对称相等,其长度为2,所以为2;
abaabca next[5]=0; 因为针对子串abaab ,,不存在头字串和尾字串对称,所以为0;
abaabcac next[6]=1; 因为针对子串abaabca,存在 头子串a和尾子串a对称相等,其长度为1,所以为1;
总结起来如下:
- J
- P a b a a b c a c
- next(j) -
获取next数组的代码如下
- //获取模式匹配字符串的next数组
- void getNext(char *str,char *next)
- {
- int j = ;
- int k = -;
- int length = strlen(str);
- next[] = -;
- while(j<length)
- {
- if(k == - || str[j] == str[k])
- {
- j++;
- k++;
- next[j] = k;
- }else k = next[k];
- }
- }
然后在匹配的过程中,如果遇到不匹配现象时,从不匹配位置分析,其next[i]的值标记着有n个头子串和尾子串相等,即直接从next[i]的值为下标开始寻找匹配。复杂度为O(m+n) KMP实现代码:
- //src为要匹配的字符串,pat为字符串模型
- int KMP(char *src,char *pat)
- {
- char next[];
- getNext(pat,next);
- int lengthP = strlen(pat);
- int lengthS = strlen(src);
- int posS=,posP=-;
- bool flag = false;
- while(posS < lengthS && posP < lengthP)
- {
- if (posP==- ||src[posS] == pat[posP])
- {
- if (flag)
- posS++;
- posP++;
- }else
- {
- posP = next[posP];
- flag = true;
- }
- }
- if (posP<lengthP)return -;
- else return posS-lengthP;
- }
完整的代码:
- #include<stdio.h>
- #include<string.h>
- //获取模式匹配字符串的next数组
- void getNext(char *str,char *next)
- {
- int j = ;
- int k = -;
- int length = strlen(str);
- next[] = -;
- while(j<length)
- {
- if(k == - || str[j] == str[k])
- {
- j++;
- k++;
- next[j] = k;
- }else k = next[k];
- }
- }
- //src为要匹配的字符串,pat为字符串模型
- int KMP(char *src,char *pat)
- {
- char next[];
- getNext(pat,next);
- int lengthP = strlen(pat);
- int lengthS = strlen(src);
- int posS=,posP=-;
- bool flag = false;
- while(posS < lengthS && posP < lengthP)
- {
- if (posP==- ||src[posS] == pat[posP])
- {
- if (flag)
- posS++;
- posP++;
- }else
- {
- posP = next[posP];
- flag = true;
- }
- }
- if (posP<lengthP)return -;
- else return posS-lengthP;
- }
- int main()
- {
- char src[];
- char pat[];
- printf("请输入要匹配的字符串和字符串模板(字串):\n");
- scanf("%s%s",src,pat);
- int f = KMP(src,pat);
- printf("在元字符串中匹配位置的下标为 %d ",f);
- return ;
- }
字符串匹配算法KMP算法的更多相关文章
- 字符串匹配算法——KMP算法
处理字符串的过程中,难免会遇到字符匹配的问题.常用的字符匹配方法 1. 朴素模式匹配算法(Brute-Force算法) 求子串位置的定位函数Index( S, T, pos). 模式匹配:子串的定位操 ...
- 字符串匹配算法——KMP算法学习
KMP算法是用来解决字符串的匹配问题的,即在字符串S中寻找字符串P.形式定义:假设存在长度为n的字符数组S[0...n-1],长度为m的字符数组P[0...m-1],是否存在i,使得SiSi+1... ...
- [Algorithm] 字符串匹配算法——KMP算法
1 字符串匹配 字符串匹配是计算机的基本任务之一. 字符串匹配是什么?举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串& ...
- 字符串匹配算法-kmp算法
一原理: 部分转自:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html 字 ...
- 算法数据结构 | 只要30行代码,实现快速匹配字符串的KMP算法
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法数据结构专题的第29篇文章,我们来聊一个新的字符串匹配算法--KMP. KMP这个名字不是视频播放器,更不是看毛片,它其实是由Kn ...
- 《数据结构》之串的模式匹配算法——KMP算法
//串的模式匹配算法 //KMP算法,时间复杂度为O(n+m) #include <iostream> #include <string> #include <cstri ...
- 字符串匹配算法 -- Rabin-Karp 算法
字符串匹配算法 -- Rabin-Karp 算法 参考资料 1 算法导论 2 lalor 3 记忆碎片 Rabin-karp 算法简介 在实际应用中,Rabin-Karp 算法对字符串匹配问题能较好的 ...
- Java数据结构之字符串模式匹配算法---KMP算法2
直接接上篇上代码: //KMP算法 public class KMP { // 获取next数组的方法,根据给定的字符串求 public static int[] getNext(String sub ...
- Java数据结构之字符串模式匹配算法---KMP算法
本文主要的思路都是参考http://kb.cnblogs.com/page/176818/ 如有冒犯请告知,多谢. 一.KMP算法 KMP算法可以在O(n+m)的时间数量级上完成串的模式匹配操作,其基 ...
随机推荐
- Kinect2.0关节角度获取
通过Kinect获取到关节的三维坐标点后可以根据向量点积或叉积公式计算出关节角度: $$\vec{a}\cdot \vec{b} = |\vec{a}||\vec{b}|cos\theta$$ vec ...
- Ubuntu 1604配置安装mysql8.0
安装步骤: 一.通过APT方式安装 说明:此种方式完全参考官方提供的教程https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/. 注意:通过A ...
- 管理多tomcat实例的shell脚本
为了简化tomcat的部署复杂度, 把以前单独配置的脚本提出来做了一个带参数的, 可以用于单机环境下的多tomcat实例管理. 其中deploy功能, 会将指定的模块war按日期时间更名备份后, 再部 ...
- Utils--封装好的下载图片的方法
/** * 封装下载图片方法 * @param url 下载地址 * @param filename * @return 下载成功为true */ public boolean downfile(St ...
- Dockerfile 构建前端node应用cnpm命令启动nodejs服务
cat Dockerfile.node FROM centos MAINTAINER zha*****ch.cn ENV LANG en_US.UTF-8 RUN /bin/cp /usr/share ...
- c++ remove_if
#include <algorithm> 函数remove_if()移除序列[start, end)中所有应用于谓词p返回true的元素. 此函数返回一个指向被修剪的序列的最后一个元素迭代 ...
- std::string std::wstring 删除最后元素 得到最后元素
std::string str = "abcdefg,"; std::cout << "last character:"<<str.ba ...
- postmessage and sendmessage
从msdn上看二者的解释: postmessage : Places (posts) a message in the message queue associated with the thread ...
- 蛋疼的经历--wireshark不能启动的问题
事情是这样子的,最近新入职,安装了wireshark,,,在急需要其观察数据包结构,,,,写代码时,,,,卡了,,,我的天!!! 刚开始是提示说,找不到动态链接库api-ms-win-crt-runt ...
- 为什么你学不会递归?告别递归,谈谈我的一些经验 关于集合中一些常考的知识点总结 .net辗转java系列(一)视野 彻底理解cookie,session,token
为什么你学不会递归?告别递归,谈谈我的一些经验 可能很多人在大一的时候,就已经接触了递归了,不过,我敢保证很多人初学者刚开始接触递归的时候,是一脸懵逼的,我当初也是,给我的感觉就是,递归太神奇了! ...