【数据结构】KMP算法:计算next与nextval函数值(图解)

:计算模式串"abaabcac"的KMP算法中next函数值

由函数定义
n e x t [ j ] = { 0 ,   j = 1 M a x { k ∣ 1 < k < j 且 " t 1 t 2 ⋅ ⋅ ⋅ t k − 1 " = " t j − k + 1 t j − k + 2 ⋅ ⋅ ⋅ t j − 1 " } 1 ,   k = 1 next[j]=\left\{ \begin{aligned} 0 , & \ j=1 \\ Max & \{k|1<k<j且"t_1t_2···t_{k-1}"="t_{j-k+1}t_{j-k+2}···t_{j-1}" \} \\ 1 , & \ k=1 \end{aligned} \right. next[j]= 0,Max1, j=1{k∣1<k<j"t1t2⋅⋅⋅tk1"="tjk+1tjk+2⋅⋅⋅tj1"} k=1
可得 next[1] = 0,其修正值 nextval[1] = 0

对模式串进行自我匹配的过程如图所示:(主串指针i,子串指针j
在这里插入图片描述
故计算得到的函数值为:

模式串abaabcac
j12345678
next[j]01122312
nextval[j]01020302
在C++中,KMP算法(Knuth-Morris-Pratt 算法)通常用于字符匹配问题,包括计算某个模式在主中的位置。针对4.3节的例题"abbabcac",我们首先要创建一个next数组存储前缀函数的结果,然后遍历主查找模式。以下是一个简单的C++代码实现: ```cpp #include <iostream> #include <vector> // 计算next数组 std::vector<int> get_next(const std::string& pattern) { int len = pattern.length(); std::vector<int> next(len); int j = -1; for (int i = 0; i < len; ++i) { while (j != -1 && pattern[i] != pattern[j + 1]) { j = next[j]; } if (pattern[i] == pattern[j + 1]) { j++; } next[i] = j; } return next; } // KMP匹配主 int kmp_search(const std::string& main_str, const std::string& pattern) { int len_main = main_str.length(), len_pattern = pattern.length(); std::vector<int> next = get_next(pattern); int index = 0, j = 0; while (index < len_main) { if (main_str[index] == pattern[j]) { index++, j++; } else if (j != 0) { j = next[j - 1]; // 如果当前字符不匹配,回溯到next[j - 1] } else { index++; // 主继续匹配下一个字符 } if (j == len_pattern) { // 找到了匹配的模式 return index - j; } } return -1; // 没有找到匹配 } int main() { std::string main_str = "abbabcac"; std::string pattern = "abc"; int result = kmp_search(main_str, pattern); if (result != -1) { std::cout << "Pattern found at position " << result << std::endl; } else { std::cout << "Pattern not found" << std::endl; } return 0; } ``` 在这个例子中,`kmp_search` 函数首先计算了 `pattern` 的前缀函数 `next`,然后遍历 `main_str` 通过比较和回溯操作寻找 `pattern`。如果找到匹配,返回开始位置;否则返回 -1 表示未找到。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值