字符串比较 kmp算法 Leetcode 28 Leetcode 1392

这里分享下我学习KMP的心得

KMP算法是三位计算机科学家发明的字符串匹配算法。
从暴力逐个比对到最大公共前后缀优化

next数组

假设已经得到next数组,使用数组进行字符串匹配的流程如上,代码如下

const int N = 100010, M = 1000010;
int n, m;
int ne[N];
char s[M], p[N];
{

    for (int i = 1, j = 0; i <= m; i ++ )
    {
        while (j && s[i] != p[j + 1]) j = ne[j];
        if (s[i] == p[j + 1]) j ++ ;
        if (j == n)
        {
            //ok  得到答案
            return 0;
        }
    }
}

//==================================================================
下面我们来进行next数组的计算
Next数组就是计算某个坐标之前的字符串的能匹配的前缀与后缀的长度
本质上就是自己和自己的匹配

int n, m;
int ne[N];
char s[M], p[N];
for (int i = 2, j = 0; i <= n; i ++ )
{
   while (j && p[i] != p[j + 1]) j = ne[j];
   if (p[i] == p[j + 1]) j ++ ;
   ne[i] = j;
}

下面来试试代码实现解决Leetcode 28. 实现 strStr()
地址 https://leetcode-cn.com/problems/implement-strstr/

实现 strStr() 函数。
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。
如果不存在,则返回  -1 。

说明:
当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。

示例 1:
输入:haystack = "hello", needle = "ll"
输出:2

示例 2:
输入:haystack = "aaaaa", needle = "bba"
输出:-1

示例 3:
输入:haystack = "", needle = ""
输出:0

提示:
0 <= haystack.length, needle.length <= 5 * 104
haystack 和 needle 仅由小写英文字符组成

解答 使用kmp算法解决该题

class Solution {
public:
	int ne[50010];
	int strStr(string haystack, string needle) {
		if (needle.empty()) return 0;
		memset(ne, 0, sizeof ne);
		int m = haystack.size();
		int n = needle.size();
		haystack.insert(haystack.begin(), '#');
		needle.insert(needle.begin(), '#');

		for (int i = 2, j = 0; i <= n; i++)
		{
			while (j && needle[i] != needle[j + 1]) j = ne[j];
			if (needle[i] == needle[j + 1]) j++;
			ne[i] = j;
		}

		for (int i = 1, j = 0; i <= m; i++)
		{
			while (j && haystack[i] != needle[j + 1]) j = ne[j];
			if (haystack[i] == needle[j + 1]) j++;
			if (j == n)
			{
				return i - n;
			}
		}

		return -1;
	}
};

Leetcode 1392 最长快乐前缀
地址 https://leetcode-cn.com/problems/longest-happy-prefix/

「快乐前缀」是在原字符串中既是 非空 前缀也是后缀(不包括原字符串自身)的字符串。
给你一个字符串 s,请你返回它的 最长快乐前缀。
如果不存在满足题意的前缀,则返回一个空字符串。

示例 1:
输入:s = "level"
输出:"l"
解释:不包括 s 自己,一共有 4 个前缀("l", "le", "lev", "leve")和 4 个后缀("l", "el", "vel", "evel")。
最长的既是前缀也是后缀的字符串是 "l" 。

示例 2:
输入:s = "ababab"
输出:"abab"
解释:"abab" 是最长的既是前缀也是后缀的字符串。题目允许前后缀在原字符串中重叠。

示例 3:
输入:s = "leetcodeleet"
输出:"leet"

示例 4:
输入:s = "a"
输出:""
 

提示:
1 <= s.length <= 10^5
s 只含有小写英文字母

解法 求最长的公共前缀后缀 就是kmp中next数组的过程

class Solution {
public:
    int ne[100010];
    string longestPrefix(string s) {
        int n = s.size();
        s.insert(s.begin(), '#');
        memset(ne, 0, sizeof ne);
        for (int i = 2, j = 0; i <= n; i++)
		{
			while (j && s[i] != s[j + 1]) j = ne[j];
			if (s[i] == s[j + 1]) j++;
			ne[i] = j;
		}

        int len = ne[s.size()-1];

        return s.substr(1,len);

    }
};

我的视频题解空间

posted on 2021-09-19 17:38  itdef  阅读(93)  评论(0编辑  收藏  举报

导航