[LeetCode]KMP——字符串匹配

13 篇文章 0 订阅
4 篇文章 0 订阅

一、问题描述:

https://leetcode.com/problems/implement-strstr/

Implement strStr().

Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

Subscribe to see which companies asked this question

二、实现:

暴力匹配

    int strStr(string haystack, string needle) {
    	if (haystack.length() < needle.length()) {
    		return -1;
    	}
    	if (haystack.length() == needle.length()) {
    		if (haystack == needle) {
    			return 0;
    		}
    		return -1;
    	}
        for (int i = 0; i < haystack.length()-needle.length()+1; ++i) {
        	string tmp = haystack.substr(i, needle.length());
        	cout << tmp << endl;
        	if (tmp == needle) {
        		return i;
        	}
        }
        return -1;
    }


KMP

注意大坑!

j<(int)needle.length()

不加(int)的话,由于length()为无符号类型,当j==-1时将会被转化为INT_MAX!

public:
    int strStr(string haystack, string needle) {
    	if (needle.empty()) return 0;
    	if (haystack.empty()) return -1;
    	if (haystack.length() == needle.length()) {
    		if (haystack == needle) return 0;
    		return -1;
    	}
    	vector<int> nextArray(needle.length(), 0);
    	generateNext(nextArray, needle);
    	int i = 0, j =0;
    	while(i<haystack.length() && j<(int)needle.length()) {
    		if (j==-1 || haystack[i]==needle[j]) {
    			i++;
    			j++;
    		}
    		else j = nextArray[j];
    	}
    	if (j == needle.length()) return i-j;
    	return -1;
    }
private:
    void generateNext(vector<int> &nextArray, string needle) {
    	nextArray[0] = -1;
    	int k = -1, j = 0;
    	while(j < needle.length()-1) {
    		if (k==-1 || needle[k]==needle[j]) {
    			k++;
    			j++;
    			if (needle[j] != needle[k]) nextArray[j] = k;
    			else nextArray[j] = nextArray[k];
    		}
    		else k = nextArray[k];
    	}
    }
======================================================================================================================
最近做一道题,用到上面这种KMP写法,但是却超时了。
理论上10^6的长度应该是不会超过1s的,翻了一下算法导论,将上述KMP算法更改如下:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;
void generateNext(vector<int> &nextArray, string needle) {
	nextArray[0] = -1;
	int k=-1, q;
	for (q = 1; q < needle.length(); ++q) {
		while (k>=0 && needle[k+1]!=needle[q])
			k = nextArray[k];
		if (needle[k+1] == needle[q]) 
			k++;
		nextArray[q] = k;
	}
	// for (int i = 0; i < needle.length(); ++i) {
	// 	cout << nextArray[i] << endl;
	// }
}
int match(string hayStack, string needle, vector<int>& nextArray) {
	if (hayStack.length() < needle.length()) return 0;
	if (hayStack.length() == needle.length()) {
		if (hayStack == needle) return 1;
		return 0;
	}
	int q=-1, i=0;
	int cnt=0;
	for (i = 0; i < hayStack.length(); ++i) {
		while (q>=0 && needle[q+1]!=hayStack[i])
			q = nextArray[q];
		if (needle[q+1] == hayStack[i])
			q++;
		if (q == needle.length()-1) {
			cnt++;
			q = nextArray[q];
		}
	}
	return cnt;
}
int main(int argc, char const *argv[]) {
	string hayStack, needle;
	while (cin >> hayStack >> needle) {
		vector<int> nextArray(needle.length(), 0);
		generateNext(nextArray, needle);
		int cnt = match(hayStack, needle, nextArray);
		cout << cnt << endl;
	}
	return 0;
}


附:KMP讲解 http://blog.csdn.net/v_july_v/article/details/7041827


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。 KMP算法的核心思想是利用已知信息来避免不必要的字符比较。具体来说,它维护一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从模式串的第next[i]个字符开始。 我们可以通过一个简单的例子来理解KMP算法的思想。假设文本串为S="ababababca",模式串为P="abababca",我们想要在S中查找P的出现位置。 首先,我们可以将P的每个前缀和后缀进行比较,得到next数组: | i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | - | - | - | - | - | - | - | - | | P | a | b | a | b | a | b | c | a | | next| 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 接下来,我们从S的第一个字符开始匹配P。当S的第七个字符和P的第七个字符匹配失败时,我们可以利用next[6]=4,将P向右移动4个字符,使得P的第五个字符与S的第七个字符对齐。此时,我们可以发现P的前五个字符和S的前五个字符已经匹配成功了。因此,我们可以继续从S的第六个字符开始匹配P。 当S的第十个字符和P的第八个字符匹配失败时,我们可以利用next[7]=1,将P向右移动一个字符,使得P的第一个字符和S的第十个字符对齐。此时,我们可以发现P的前一个字符和S的第十个字符已经匹配成功了。因此,我们可以继续从S的第十一个字符开始匹配P。 最终,我们可以发现P出现在S的第二个位置。 下面是KMP算法的C++代码实现:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值