小白带你学kmp 不会找我拿红包~~

难的部分是怎么弄next数组 都是从小往大推 kmp的精髓就在next数组 一旦不匹配 通过next数组找到最大匹配长度

相信我 认真看我的代码(复制到你们的编辑器中) 和我的注释 再手动模拟一下 肯定能明白 ,不明白私聊我 ~~

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<set>
#include<map>
using namespace std;

typedef long long ll;
const int maxn = 10005;
string s, p;
int Next[maxn];
int cnt;
int slen, plen;

void getfail() {
	memset(Next, 0, sizeof(Next));
	Next[0] = 0; Next[1] = 0;
	for (int i = 1; i < plen; i++) {

		int j = Next[i];           //j:代表能够匹配的下标 

		while (j && p[i] != p[j]) {//弹出来的j 不是0 就是两个串相同的 最大下标 也就是公共长度
			j = Next[j];
		}
		Next[i + 1] = (p[i] == p[j]) ? j + 1 : 0;
	}
}

void kmp() {
	int last = 0;
	slen = s.size();
	plen = p.size();
	getfail();//求next 最大前缀
	int j = 0;
	for (int i = 0; i < slen; i++) {

		/*假如说 在下标 == 4的时候 与主串不匹配 它就会从进入while语句 找到s[i] == p[j]
			返回next【j】 然后从next【j】继续匹配

			举个例子:
			i下标  0 1 2 3 4 5 6 7 8 9
			主串   A B C A B C D H I J

			j子串  A B C A B B _
			nex的  0 0 0 0 1 2 0

			当i = 5时 此时j = 5 显然不匹配 进入while-- > 更新:j = 2 -- > s[i] = p[j] -- > 退出  
			以此类推 一直寻找......


		*/
		while (j && s[i] != p[j]) {//不同就往前 0 就重新找
			j = Next[j];		  //不然 找到当前不符合的位置 前缀又相等的情况
		}


		if (s[i] == p[j]) {     //紧随其后  如果找到同的 继续移动 j 判断下一个
			j++;
		}

		if (j == plen) {//计数 根据自己的需要 自己改
				cnt++;	//给两道题你们就知道怎么改了HDU 2087,1686
		}

	}
}
int main() {
	//freopen("888.txt", "r", stdin);
	cin >> s >> p;
	kmp();
	printf("%d\n", cnt);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
KMP算法是一种用于字符串匹配的算法,用于在一个长字符串中查一个短字符串是否存在。这个算法的核心思想是通过利用已经匹配过的部分,跳过一些不必要的比较,以提高算法的效率。 在python中使用KMP算法出最小重复子串的步骤如下: 1. 构建next数组,用于指示在匹配过程中出现不匹配时,应该将模式串向右移动多少位。 2. 初始化主串的索引`i`为0,模式串的索引`j`为0。 3. 当`i`小于主串的长度且`j`小于模式串的长度时,进行以下处理: a. 如果主串和模式串在当前位置的字符相等,则将`i`和`j`分别加1。 b. 如果主串和模式串在当前位置的字符不相等,则根据next数组的值移动模式串的索引`j`。 4. 如果在循环过程中,模式串的索引`j`达到了模式串的长度,表示模式串已经完全匹配主串了,此时到了一个最小重复子串。 5. 返回模式串的长度作为最小重复子串的长度。 下面是一个简单的Python代码示例: ```python def getNext(pattern): next = [0] * len(pattern) i, j = 1, 0 while i < len(pattern): if pattern[i] == pattern[j]: next[i] = j + 1 i += 1 j += 1 elif j > 0: j = next[j-1] else: next[i] = 0 i += 1 return next def getMinRepeatedSubstring(string): pattern = '' for i in range(1, len(string)): pattern = string[:i] next = getNext(pattern) j = 0 for c in string: if c == pattern[j]: j += 1 if j == len(pattern): return len(pattern) elif j > 0: j = next[j-1] return -1 # 测试 string = 'abcdabcdabcd' result = getMinRepeatedSubstring(string) print(result) # 输出 4,表示最小重复子串的长度为4,即'abcd' ``` 以上代码中,`getNext()`函数用于构建next数组,`getMinRepeatedSubstring()`函数用于出最小重复子串的长度。 希望以上回答对您有帮助!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DongGu.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值