hihoCoder#1015_KMP算法
来源:互联网 发布:网络穿越剧电视剧大全 编辑:程序博客网 时间:2024/04/29 20:49
题目:KMP算法
我的ac代码:
#include <iostream>#include <string>void GetNext(const std::string T, int *& next){int i = 0;int j = -1;int len = T.length();next[0] = -1;while (i < len){if (j == -1 || T[i] == T[j])next[++i] = ++j;elsej = next[j];}}int KMP(const std::string& S, const std::string& T, int *& next){int i = 0, j = 0;int sum = 0;while (i < S.size()){if (j == -1 || S[i] == T[j]){if (j == T.size() - 1){++sum;j = next[j];}else{++i;++j;}}elsej = next[j];}return sum;}int main(){int N;std::string S, T;std::cin >> N;while (N--){std::cin >> T >> S;int *next=new int [T.size()+1];GetNext(T, next);std::cout << KMP(S, T, next) << std::endl;T.clear();S.clear();delete []next;next = NULL;}return 0;}
之前对KMP算法不是很了解,看了一些资料后感觉理解了一点,下面自己写下自己对KMP的认识吧。
看了很多资料,真的是乱,有些数组从0开始,有些从1开始,看的头疼,这里是从0开始的。
我觉得,KMP算法主要是next数组的理解,我们先假设主串为: ,模式串为。那么,当主串和模式串失配时,假设失配位置为和,即,此时模式串向右滑动的可行距离有多远,也就是说,当主串第个字符和模式串第个字符失配时,主串第(不会回溯)个字符应该和模式串哪个字符比较?
我们假设此时主串第个字符应该与模式串的第个字符继续比较,则模式串前个字符必有下列关系式:
(1)
又因为失配位置是在和(),也就是说,模式串第位置前面的字符和主串是匹配的,即:
(2)
(2)式中,我们如果只取“部分”,即取k个字符,,则:
(3)
那么,由式(1)和(3),可以得到:
(4)
如果令,那么,这个的含义就是式(4)。
并且,由k的用途我们知道,的意思就是,模式串中第个字符不匹配,就用模式串中的第个字符和主串比较。
那么,如何求得next数组?
首先,由于我们的字符串下标从0开始,所以:
,
然后,我们设,由的含义(4)知,模式串存在如下关系:
(就是式(4)),
那么,此时如何计算?我们分情况讨论:
(1)
则表明模式串中存在如下关系:
(5)
根据和式(4)的关系可知,由式(5)可以得到:
(2)
我们将模式串看成一个主串,”另一个模式串“作为模式串,那么在模式串的第k位出现不匹配,所以,根据next数组的作用,应该用模式串的第个字符和主串中的比较,我们令,如果,那么有:
所以就有:
,也就是:
同样,如果,继续next,直至在模式串中找到匹配的字符,或者,“找到头”也找不到匹配的字符。
如果“找到头”也找不到匹配的字符,则:
下面,举个例子:
我们已经求得next[6]=3,现在要求next[7]。由next[6]=3得:
又
所以:
所以:
next[7]=4
我们继续求next[8],,因为next[7]=4有,但是,所以下一个和“主串”中比较的字符是第,即第1(注意,下标从0开始)个字符,此时:,继续next,,所以下一个和“主串”中比较的字符是第0个字符,有,所以,。
void Next(std::string &T,int next[]){int len = T.length();next[0] = -1;int i = 0;int j = -1;while (i < len){if (j == -1){next[i + 1] = 0;i++;j++;}else if (T[i] == T[j]){next[i + 1] = j + 1;i++;j++;}elsej = next[j];}}
我们注意到,j=-1和T[i] == T[j]内代码实现的操作是一样的(j=-1时,j+1刚好就是0),所以可以合并在一起:
void Next(std::string &T,int next[]){int len = T.length();next[0] = -1;int i = 0;int j = -1;while (i < len){if (j == -1 || T[i] == T[j]){next[i + 1] = j+1;//这里不能写next[i]+1,因为j可能是经过next[j]得到的i++;j++;}elsej = next[j];}}
再简洁一点可以写成:
void Next(std::string &T,int next[]){int len = T.length();int i = 0;int j = next[0] = -1; while (i < len){if (j == -1 || T[i] == T[j])next[++i] = ++j;elsej = next[j];}}
- hihoCoder#1015_KMP算法
- 算法竞赛_KMP算法
- 字符串匹配算法_KMP
- 模板_KMP算法
- ACM_模板_KMP算法
- 数据结构与算法_KMP算法
- C++_KMP算法的实现
- hihoCoder - 1015 - KMP算法
- [HiHoCoder]#1015 : KMP算法
- hihoCoder#1015 KMP算法
- hihocoder#1015 : KMP算法
- hihoCoder 1015 : KMP算法
- hihoCoder #1015 : KMP算法
- hihoCoder#1015 KMP算法
- hihocoder #1015 KMP算法
- hihoCoder 1015 KMP算法
- hihoCoder 1015 KMP算法
- hihocoder #1015 kmp算法
- 各种jar包下载
- JNI调用机制
- 心电图效果View Android自定义View
- python安装包方法失效或缺失问题
- CRT进程和环境-错误处理-参数访问
- hihoCoder#1015_KMP算法
- 前端web学习记录
- 41 面向对象版表达式计算器(二)
- Java 命名规范
- java 异常处理
- 使用 PHP 验证表单数据
- 【2016】三月份英语学习总结
- Tokonda Messenger(信使)
- 怎么实现字符串的反转,如:输入abc,输出cba