用KMP算法实现strStr()

strStr()函数的用途是在一个字符串S中寻找某个字串P第一次出现的位置,并返回其下标,找不到时返回-1。最简单的办法就是找出S所有的子串和P进行比较,然而这个方法比较低效。假设我们从S的下标0和P的下标0开始对每个字符进行比较,如果相等则下标增加,比较后面的字符。如果两者一直相等直到P的下标达到最大值,则表示在S中找到了P,并且第一次出现的位置为0,返回0,但如果在中间某个位置两个字符不相等时,这时S的下标要退回到1,P的下标回到0,重新开始比较。后来,有三个牛觉得这样不爽,于是他们搞了一个KMP算法,并以他们三人名字的最开始字符命名这个算法。这个算法的好处是在比较中的某个位置,两个串的字符不相等时,不需要S回退,而P的下标回退到某个值,然后继续和S当前失配的字符进行比较。

关键就是在这里了,P的下标要回退,退到哪儿啊?我们举个例子,S为“abcabcabeg”,P为"abcabe",从下标0开始比较,一直到下标5才发现字符不相等,S对应字符为c,P对应字符为e。这时候,我们就考查P中下标5以前的字符串,即“abcab”。对于这个字符串,S下标5之前也存在同样的串,我们还发现这个串的前缀和后缀都有“ab”,即下标0、1和3、4分别组成的字符串相等,同时等于S串中下标3、4组成的字符串。因此,我们只需要把P的下标退到2的位置,然后跟S的下标5对应的字符继续比较即可,因为P的0、1下标对应字符和S的3、4下标对应的字符相等。如果对于每个失配的位置,我们都这样对P的下标进行调整,而S的下标继续往前而不后退,效率会提高很多。现在最大的问题就是怎么计算P失配时应该退回到的下标值,而从前面的分析中可以看出是对字符串的前后缀相等部分的长度来获取的,这样问题就变成了怎么编写代码来较为高效地计算在失配时P调整到的新下标值。对于P中每个位置,我们可以计算出在该位置失配时应该调整到的下标,并存放在一个next数组中,比如上面P在下标为5时失配,调整到的新下标为2,则有next[5]等2。

写到这里,发现好像讲得越来越乱了,还是贴我自己的代码吧,其实KMP最关键也是不太好理解的地方就是对next数组的理解和计算方法。

void fillNext(char* p, int* next)

{

if(!p) return;

int len = strlen(p);

int i = 1;

int j = 0;

for(int i = 0; i < len; ++i) next[i] = 0;

while(i < len-1)

{

if(p[i] == p[j])

{

i++;

j++;

next[i] = j;

}

else

{

if(j == 0)

{

i++;

next[i] = 0;

}

else j = next[j];

}

}

}

int strStr(char* haystack, char* needle) {

if(!haystack || !needle) return -1;

int len_h = strlen(haystack);

int len_n = strlen(needle);

if(len_n > len_h) return -1;

if(len_n == 0) return 0;

int* next = malloc(sizeof(int)*len_n);

fillNext(needle, next);

int i = 0;

int j = 0;

while(i < len_h)

{

if(haystack[i] == needle[j])

{

j++;

i++;

if(j == len_n)break;

}

else

{

if(j == 0)i++;

else j = next[j];

}

}

free(next);

if(j == len_n)

{

return i - len_n;

}

return -1;

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-12 12:10:23

用KMP算法实现strStr()的相关文章

Implement strStr() &amp;&amp; kmp算法

用这题复习下kmp算法.kmp网上坑爹的是有很多种匹配方式,容易混淆,后人要警惕啊.这里对要查找的字符串的next全部置为-1,预处理时i和next[i-1]+1相比较.和http://kb.cnblogs.com/page/176818/ 这里相似.预处理完再匹配,第i个字符不匹配则比较第next[i-1]+1个. class Solution{ public: char *strStr(char *haystack, char *needle){ if(haystack == NULL ||

Linux GCC下strstr的实现以及一个简单的Kmp算法的接口

今天做了一道题,要用判断一个字符串是否是另一个字符串的子串,于是查了一下strstr的实现. 代码如下: 1 char *strstr(const char*s1,const char*s2) 2 { 3 const char*p=s1; 4 const size_t len=strlen(s2); 5 for(;(p=strchr(p,*s2))!=0;p++) 6 { 7 if(strncmp(p,s2,len)==0) 8 return (char*)p; 9 } 10 return(0)

leetcode_28题——Implement strStr()(采用KMP算法,还没AC,但自己这边测试无误)

Implement strStr() Total Accepted: 49294 Total Submissions: 223057My Submissions Question Solution Implement strStr(). Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. Update (2014-11-02):The s

70. Implement strStr() 与 KMP算法

Implement strStr() Implement strStr(). Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack. MY: Question. 思路: 逐步查找.当出现不同时,如何回溯是关键. Solution A: class Solution { public: char *strStr(char *haystack

算法 - KMP算法

1 解决问题 从一个字符串中查找子串,如果存在返回字串在字符串中的位置. 示例: 字符串(T):"BBC ABCDAB ABCDABCDABDE" 子串( P):"ABCDABD" 通过算法查找字串P在字符串T中的位置为15(从0开始). 2 暴力算法 思路: 循环T,从T的每个字符开始子字串P匹配. 代码: int strstr(char iTarget[], int iTLen, char iPattern[], int iPLen) { for (int i

KMP算法小结

今天又把KMP算法看了一遍,特此小结. 扯淡的话: KMP算法主要用来模式匹配.正如Implement strStr() 中形容的一样,“大海捞针”,当时看到题中变量如此命名,真的感觉实在是再贴切不过了. 在介绍KMP算法之前,先介绍一下BF算法,叫的这么暧昧(who is GF?),其实就是最low的暴力算法.这个男票略暴力. 事实上,JDK1.7中String的contains的源码用的就是BF算法.(1.7中调用了indexOf,我记得1.6中是直接写的contains接口来着) 截取了一

POJ 3461 Oulipo KMP算法题解

本题就是给出很多对字符串,然后问一个字符串在另外一个字符串出现的次数. 就是所谓的Strstr函数啦. Leetcode有这道几乎一模一样的题目. 使用KMP算法加速,算法高手必会的算法了. 另外看见讨论说什么使用KMP还超时,最大可能是没有真正理解next table的含义,写了错误的代码,故此虽然自己运行结果正确,但是却没有真正发挥next table的作用,使得算法退化为暴力法了,所以运行正确,但超时. KMP参考: http://blog.csdn.net/kenden23/articl

[2016-02-03][KMP算法]

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 const int maxn = 1E5 + 10; const int maxm = 1E4 + 10; int next[maxm]; int kkk[maxn]; void makenext(char P[]){         //m p中的元素的数目         //next[i] 表示 P和P自己匹配,

【数据结构&amp;&amp;算法系列】KMP算法介绍及实现(c++ &amp;&amp; java)

KMP算法如果理解原理的话,其实很简单. KMP算法简介 这里根据自己的理解简单介绍下. KMP算法的名称由三位发明者(Knuth.Morris.Pratt)的首字母组成,又称字符串查找算法. 个人觉得可以理解为最小回溯算法,即匹配失效的时候,尽量少回溯,从而缩短时间复杂度. KMP算法有两个关键的地方,1)求解next数组,2)利用next数组进行最小回溯. 1)求解next数组 next数组的取值只与模式串有关,next数组用于失配时回溯使用. 在简单版本的KMP算法中,每个位置 j 的 n