模式匹配KMP
字符串朴素模式匹配算法的2种实现:
//1.朴素的模式匹配算法,用while实现
int StrStr_While(const char* pStr, const char* pSub, int* pos)
{
int nRet = 0;
int pStrLen = strlen(pStr);
int pSubLen = strlen(pSub);
int i = 0, j = 0;
int nLen = pStrLen - pSubLen; if (pStr == NULL || pSub == NULL)
{
nRet = -1;
printf("param input error!");
return nRet;
} while (i < pStrLen && j < pSubLen)
{
if (*(pStr + i) == *(pSub + j))
{
++i;
++j;
}
else
{
i = i - j + 1;
j = 0;
}
} if (j == pSubLen)
*pos = i - j + 1; return nRet;
}
//2.朴素的模式匹配,用for循环实现
int StrStr_For(const char* pStr, const char* pSub, int* pos)
{
int nRet = 0;
int pStrLen = strlen(pStr);
int pSubLen = strlen(pSub);
int i = 0, j = 0;
int nLen = pStrLen - pSubLen; if (pStr == NULL || pSub == NULL)
{
nRet = -1;
printf("param input error!");
return nRet;
} for (i = 0; i <= nLen; ++i)
{
for (j = 0; j < pSubLen; ++j)
{
if (*(pStr + i + j) != *(pSub + j))
break;
} if (j == pSubLen)
{
*pos = i + 1;
break;
}
} return nRet;
}
实现字符串的匹配有高效的算法。那就是KMP算法,实现例如以下:
//取得KMP算法须要用的的next数组
int GetNext(const char* pStr, int nNext[])
{
int nRet = 0;
if (pStr == NULL || nNext == NULL)
{
nRet = -1;
printf("param input error!\n");
return nRet;
} int nLen = strlen(pStr);
int i = 0, j = -1;
nNext[i] = j;
while (i < nLen - 1)
{
if (j == -1 || pStr[i] == pStr[j])
{
++i;
++j;
nNext[i] = j;
}
else
{
j = nNext[j];
}
} return nRet;
} //取next数组的改进型算法!剔除多个反复字符的next数组值持续增长。 int GetNextVal(const char* pStr, int nNext[]) { int nRet = 0; if (pStr == NULL || nNext == NULL) { nRet = -1; printf("param input error!\n"); return nRet; } int nLen = strlen(pStr); int i = 0, j = -1; nNext[i] = j; while (i < nLen - 1) { if (j == -1 || pStr[i] == pStr[j]) { ++i; ++j; if (pStr[i] != pStr[j]) nNext[i] = j; else nNext[i] = nNext[j]; } else { j = nNext[j]; } } return nRet; }
这是针对类似aaaaaaab这种字符串使用上面两个函数取得的next数组值得比較。注意书上的都是字符串从数组的下标为1的位置開始存储的。我改进的算法是还是让字符串从数组下标为0的位置開始存储。
所以上面的next数组值都要相较与原来的值减1。
//调用上面的函数实现KMP高效字符串模式匹配算法!
int Index_KMP(const char* pStr, const char* pSub, int* nPos)
{
int nRet = 0;
if (pStr == NULL || pSub == NULL || nPos == NULL)
{
nRet = -1;
printf("param input error!\n");
return nRet;
} int pStrlen = strlen(pStr);
int pSublen = strlen(pSub); int nNext[255] = { 0 };
//nRet = GetNext(pSub,nNext);
nRet = GetNextVal(pSub, nNext);
if (nRet != 0)
{
printf("call GetNext() func is error!\n");
return nRet;
} int i = 0, j = 0;
while (i < pStrlen && j < pSublen)
{
if (j == -1 || *(pStr + i) == *(pSub + j))
{
++i;
++j;
}
else
{
j = nNext[j];
}
} if (j == pSublen)
*nPos = i - j + 1; return nRet;
}
模式匹配KMP的更多相关文章
- 字符串模式匹配KMP算法
一篇不错的博客:http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html KMP字符串模式匹配通俗点说就是一种在一个字符串中 ...
- 『字符串模式匹配 KMP』
字符串模式匹配 我们要先了解一下问题是什么. 模式匹配是数据结构中字符串的一种基本运算,给定一个子串,要求在某个字符串中找出与该子串相同的所有子串,这就是模式匹配. KMP 然后我们来认识一下今天的主 ...
- 字符串模式匹配——KMP算法
KMP算法匹配字符串 朴素匹配算法 字符串的模式匹配的方法刚开始是朴素匹配算法,也就是经常说的暴力匹配,说白了就是用子串去和父串一个一个匹配,从父串的第一个字符开始匹配,如果匹配到某一个失配了,就 ...
- 模式匹配KMP算法
关于KMP算法的原理网上有很详细的解释,我试着总结理解一下: KMP算法是什么 以这张图片为例子 匹配到j=5时失效了,BF算法里我们会使i=1,j=0,再看s的第i位开始能不能匹配,而KMP算法接下 ...
- 模式匹配-KMP算法
/***字符串匹配算法***/ #include<cstring> #include<iostream> using namespace std; #define OK 1 # ...
- 数据结构4.3_字符串模式匹配——KMP算法详解
next数组表示字符串前后缀匹配的最大长度.是KMP算法的精髓所在.可以起到决定模式字符串右移多少长度以达到跳跃式匹配的高效模式. 以下是对next数组的解释: 如何求next数组: 相关链接:按顺序 ...
- KMP及其改进算法
本文主要讲述KMP已经KMP的一种改进方法.若发现不正确的地方,欢迎交流指出,谢谢! KMP算法的基本思想: KMP的算法流程: 每当一趟匹配过程中出现字符比较不等时,不需回溯 i 指针,而是利用已经 ...
- acm算法模板(1)
1. 几何 4 1.1 注意 4 1.2 几何公式 4 1.3 多边形 6 1.4 多边形切割 9 1.5 浮点函数 10 1.6 面积 15 1.7 球面 16 1.8 三角形 17 1.9 三维几 ...
- ACM-ICPC竞赛模板
为了方便打印,不再将代码放到代码编辑器里,祝你好运. ACM-ICPC竞赛模板(1) 1. 几何 4 1.1 注意 4 1.2 几何公式 4 1.3 多边形 6 1.4 多边形切割 9 1.5 浮点函 ...
随机推荐
- jQuery.fn.serialize 阅读
今天第一次阅读jQuery源码,因为读到用js对表单的序列化,为的是在ajax操作中将表单中各个域的值传到服务器.书上用了很长的步骤,判断每一个表单域的属性,然后拼接. 大概是这样: function ...
- 使用Lock实现信号量
public class SemaphoreOnLock { private final Lock lock = new ReentrantLock(); private fi ...
- Java之旅(一)---说说“异常”那些事
从開始学习VB,就听说过"异常",认为异常处理就是加上try..catch,不让错误抛出给用户,到此为止,不要再往下问了,再问也不会了.这就是那时候的理解.如今随时项目经验的 ...
- Memory Architecture-SGA-Database Buffer Cache
启动instance:1.分配内存空间SGA 2.启动后台进程 内存结构:1.SGA 2.PGA 3.UGA 4.Software code areas SGA components:1.Databa ...
- 界面调试工具Reveal的使用介绍
Reveal 注: 此处介绍Reveal,其中大部分内容来自于唐巧的<iOS开发进阶>一书,以此说明. 如何使用Reveal进行模拟器调试,只需进行以下三个步骤即可. 1. 创建.lldb ...
- ssh登陆笔记📒
ssh的配置 ssh的配置文件在/etc/ssh下,有两种配置文件,ssh_config和sshd_config. ssh_config是针对客户端的配置文件, sshd_config是针对服务端的配 ...
- 什么是DNS劫持和DNS污染?
什么是DNS劫持和DNS污染? http://blogread.cn/it/article/7758?f=weekly 说明 我们知道,某些网络运营商为了某些目的,对 DNS 进行了某些操作,导致使用 ...
- BZOJ 1875: [SDOI2009]HH去散步( dp + 矩阵快速幂 )
把双向边拆成2条单向边, 用边来转移...然后矩阵乘法+快速幂优化 ------------------------------------------------------------------ ...
- 问题解决: WordPress on SAE注册邮件无法发送
方法一: 修改代码 Step 1: 改写wp-includes/pluggable.php, 把WordPress默认邮件设置改为SMTP模式. // Set to use PHP's mail() ...
- Android 6.0 新特性 整理 资料来自网络
Android 6.0新特性 Runtime Permissions Doze and App Standby Apache HTTP Client Removal BoringSSL Access ...