字符串-KMP的模式匹配算法
来源:互联网 发布:返利 知乎 编辑:程序博客网 时间:2024/06/01 15:08
KMP算法中,主要的是如何得到next数组;
假设:
已知模式字符串P的next[0,….,j],且next[j] = k,如何求出next[j+1]?
递归公式:
若P[k] = P[j] , 则next[j + 1] = next[j] + 1 = k + 1;
若P[k] != P[j] , 如果此时P[next[k]] = P[j], 则next[j + 1] = k + 1,否则继续递归索引 k=next[k];
void GetNext(char *P, int next[]){ int pLen = strlen(P); next[0] = -1; int prefix = -1; int suffix = 0; while (suffix < pLen - 1) { if (prefix == -1 || P[prefix] == P[suffix]) { next[suffix + 1] = prefix + 1;//此处这么写,容易理解 ++prefix; ++suffix;//只有此处,才会递增模式字符串的索引suffix } else { //若不相等,则执行递归,直到找到相等,或是找到开头 prefix = next[prefix]; } }}
在了解next数组前,还需要知道前缀和后缀的概念:
- “前缀”指除了最后一个字符以外,一个字符串的全部头部组合;
- “后缀”指除了第一个字符以外,一个字符串的全部尾部组合。
以“ABCDABD”为例:
- “A”的前缀和后缀都为空集,共有元素的长度为0;
- “AB”的前缀为[A],后缀为[B],共有元素的长度为0;
- “ABC”的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;
- “ABCD”的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;
- “ABCDA”的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为”A”,长度为1;
- “ABCDAB”的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为”AB”,长度为2;
- “ABCDABD”的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。
本文参考了网上的一些帖子,以及部分算法书籍。
KMP算法的优化:
考虑模式字符串为”abab“的情况:
- 它的前缀后缀最大长度为0,0,1,2;
- 进行右移一位后,得到的next数组为-1,0,0,1;
- 倘若文本字符串为“abacxxxxx“ ,在比较到”c“,发现出现不相同字符,按照之前的next数组,需要移动 3 - next[3] = 3 - 1 = 2后,模式字符串中的P[1]字符b,仍然和文本字符的c不同。所以,匹配失败;即,不能使P[j] != P[next[j] ]。如果出现了该情况,需要执行递归,next[j] = next[ next[j] ]。
void GetNext(char *P, int next[]){ int pLen = strlen(P); next[0] = -1; int prefix = -1; int suffix = 0; while (suffix < pLen - 1) { if (prefix == -1 || P[prefix] == P[suffix]) { //优化后 if (P[prefix + 1] != P[suffix + 1]) { next[suffix + 1] = prefix + 1;//优化之前,只有该行 } else { next[suffix + 1] = next[prefix + 1]; } ++prefix; ++suffix;//只有此处,才会递增模式字符串的索引suffix } else { //若不相等,则执行递归,直到找到相等,或是找到开头 prefix = next[prefix]; } }}
完整的kmp字符串匹配算法的代码为:
int KMPSearch(char *s, char *p){ int len1 = strlen(s); int len2 = strlen(p); int *next = new int[len2]; GetNext(p, next); int i = 0; int j = 0; while (i < len1 && j < len2) { //此处的-1,是next数组值;经过优化后,模式字符串的部分子字符串的next值,有可能为-1 if (j == -1 || s[i] == p[j]) { ++i; ++j; } else { j = next[j]; } } delete[] next; if (j == len2) { return (i - j); } else { return -1; } }
阅读全文
0 0
- 字符串的模式匹配算法--KMP算法
- 字符串的模式匹配算法 KMP
- 字符串模式匹配(所谓的kmp)算法
- 字符串的模式匹配:KMP算法
- 算法:字符串的KMP模式匹配
- 改良的KMP字符串模式匹配算法
- 字符串的模式匹配,KMP算法
- 字符串的模式匹配:KMP算法
- 字符串模式匹配的KMP算法
- 字符串模式匹配的KMP算法实现
- 字符串-KMP的模式匹配算法
- 字符串模式匹配KMP算法
- 字符串模式匹配KMP算法
- KMP字符串模式匹配算法
- 字符串模式匹配KMP算法
- KMP字符串模式匹配算法
- KMP字符串模式匹配算法
- 字符串模式匹配KMP算法
- 卷积神经网络
- 运行loadrunner,打不开IE问题处理方法
- python常见面试题
- 个人笔记
- 写给昨天的自己
- 字符串-KMP的模式匹配算法
- bootstrap插件bootstrapValidator常用验证规则总结
- 设计模式之工厂模式
- leetcode---permutations-ii---dfs
- Python3 输入和输出
- wordpress设置固定链接后文章出现404的解决办法 【ubuntu16.04】
- Python3 OS 文件/目录方法
- 排查中,windows部分浏览器下载文件的后缀名被更改
- VPN篇(5.6) 01. VPN 结构与需求 ❀ 飞塔 (Fortinet) 防火墙