KMP算法与string::find以及strstr的比较
来源:互联网 发布:ps淘宝抠图 编辑:程序博客网 时间:2024/06/05 04:48
首先,简单描述一下KMP算法,要理解好KMP算法,最好参考算法导论[1],尤其是先理解好自动机匹配的方法,再看KMP就很容易理解了。它利用的是一个关键的回退原理,也就是如果匹配失败时,那么我知道只要从模式的某个位置继续匹配就可以了,这个回退的位置事先通过模式计算出来,也就是说如果某个位置匹配不成功,就回退到事先算好的位置,继续匹配。这个事先算好的位置就是从0到该位置应该是匹配不成功处的一个后缀。这个过程可以通过已经算好的回退位置来递推出来。
从算法的描述看,回退的数组的构建与匹配的过程是非常相似的。
这里比较了KMP和string::find以及strstr的性能,代码如下:
#include <vector>#include <string>#include <stdio.h>#include <stdlib.h>#include <sys/time.h>#include <string.h>void ComputePrefixFun(const std::string& patten, std::vector<int>* back) { int k = -1; (*back).push_back(-1); for (int i = 1; i < patten.size(); ++i) { while (k > -1 && patten[k + 1] != patten[i]) { k = (*back)[k]; } if (patten[k + 1] == patten[i]) { k++; } (*back).push_back(k); }}void Match(const std::string& src, const std::string& patten, const std::vector<int>& back, std::vector<size_t>* offset) { int k = -1; size_t src_length = src.size(); size_t patten_length = patten.size(); for (int i = 0; i < src_length; ++i) { while (k > -1 && patten[k + 1] != src[i]) { k = back[k]; } if (patten[k + 1] == src[i]) { k++; } if (k == patten_length - 1) { (*offset).push_back(i - patten_length + 1); k = back[k]; } }}std::string IntToString(int value) { std::string res = ""; do { res.insert(0,std::string(1, value % 10 + '0')); } while ((value /= 10) >0); return res;}int GetTime() { timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000 + tv.tv_usec;}int main(int argc, char** argv) { std::string patten = "1212123"; std::vector<int> back; std::string src = ""; for (int i = 0; i < 1000000; ++i) { src += IntToString(rand()); } ComputePrefixFun(patten, &back); std::vector<size_t> offset; int start = GetTime(); Match(src, patten, back, &offset); printf("time:%d %zd\n", GetTime() - start, offset.size()); start = GetTime(); int index = -1; int count = 0; while ((index = src.find(patten, index + 1)) != std::string::npos) { count++; } printf("time:%d count = %d\n", GetTime() - start, count); const char* pos = src.c_str(); start = GetTime(); count = 0; while (true) { pos = strstr(pos, patten.c_str()); if (pos == NULL) break; pos++; count++; } printf("time:%d find:%d \n", GetTime() - start, count); std::string matched = ""; for (int i = 0; i < offset.size(); ++i) { matched = src.substr(offset[i], patten.size()); // printf("%zd %s ", offset[i], matched.c_str()); } printf("\n");}
开始编译时没有使用优化选项,结果KMP的性能总是不理想,使用-O3编译后,性能明显改善了。
参考文献
算法导论 第32章 P586
- KMP算法与string::find以及strstr的比较
- strstr函数与KMP算法比较
- 28. Implement strStr() 以及KMP算法的实现
- strstr的实现与KMP
- [Leetcode] Implement strStr()与 KMP算法
- hdu 5510 strstr/find/KMP
- strstr函数(KMP算法)
- KMP 算法 && Implement strStr()
- Implement strStr() && kmp算法
- Implement strStr() KMP算法
- String与StringBuilder以及StringBuffer的比较
- 字符串比较函数strncasecmp():比较字符串的前n个字符|字符串查找函数strstr和string.find() 查找字符串str1中是否存在与str2一样的子字符串
- LeetCode-难题集之Implement strStr()与KMP算法
- Leetcode#28. Implement strStr()(String find()函数的用法)
- KMP实现的strstr
- KMP算法实现strstr()函数
- 用KMP算法实现strStr()
- 28. Implement strStr()(KMP算法)
- linux下iconv()函数的用法
- Visual Studio 2008 、 Windows 环境变量介绍 和 如何在文件中引用环境变量
- ShadowVolume DX9
- c++primer学习笔记(3.3)标准库vector类型
- ffmpeg-0.6.3 移植到 windows 开源代码
- KMP算法与string::find以及strstr的比较
- 几句话说明 .NET MVC中ViewData, ViewBag和TempData的区别
- 作品展(一)
- 第18周作业二
- 如何从普通程序员晋升为架构师
- 花10钟看一看少走30年弯路
- 利用Windows2003 IP安全策略实现服务器远程桌面端口(3389)访问控制
- C语言查看多字节变量中每单个字节数据的方法
- Linux环境下移植qt4及qwt从零开始