字符串——扩展kmp算法

本文详细介绍了扩展KMP算法的原理和流程,通过举例解释了如何计算Extend数组,并探讨了其在解决字符串匹配和回文串判断问题中的应用。提供了一道HDU3613题目作为实例,展示如何利用扩展KMP算法解决问题。
摘要由CSDN通过智能技术生成

扩展kmp算法

原文链接:扩展kmp算法

**问题定义:**给定俩个字符串,文本串S,模式串T,长度分别为n和m,下标从0开始定义。定义Extend[]数组,Extend[i] 等于 S[i]…S[n-i] 与 T 的最长相同的前缀长度,现在问题是求出所有Extend[i]。举个例子,看下表:

i 0 1 2 3 4 5 6 7
S a a a a a b b b
T a a a a a c
Extend[i] 5 4 3 2 1 0 0 0

如果在S的某个位置 i 有Extend[i] = m,则可知在 S 中找到了模式串 T,并且匹配的首位是 i 。而且,扩展kmp算法可以找到 S 中所有 T 的匹配。

一.算法流程

(1)
1
如上图,假设当前遍历到 S 串位置 I ,即Extend[0]…Extend[i-1]这 i 个位置的值已经计算得到了。设置俩个变量 a 和 p 。代表以 a 为起始位置的字符匹配成功的最右边界,也就是 “p = 最后一个匹配成位置 + 1“。相较于字符串 T 得出,S[a…] 等于T[0…p-a]。
再定义一个辅助数组int Next[], 其中Next[i] 的含义为:T[i]…T[m-1] 与 T 的最长相同的前缀长度,m为串 T 的长度。举个例子:

i 0 1 2 3 4 5
T a a a a a c
Next[i] 6 4 3 2 1 0

(2)
2
S[i] 对应 T[i - a], 如果 i + Next[i - a] < p, 如上图,三个椭圆长度相同,根据Next数组的定义,此时 Extend[i] = Next[i - a]。

(3)
3
如果i + Next[i - a] == p呢? 如上图,三个椭圆都是完全相同的, S[p] != T[p - a] 且 T[p - i] != T[p - a], 但S[p] 有可能等于 T[p - i], 所以我们可以直接从 S[p] 与 T[p - i]开始往后匹配,加快了速度。
(4)
4
如果i + next[i - a] > p呢?那说明S[i…p)与T[i-a…p-a)相同,注意到S[p] != T[p - a]且T[p - i] == T[p - a],也就是说S[p] != T[p - i],所以就没有继续往下判断的必要了,我们可以直接将extend[i]赋值为p - i。

(5)
最后,就是求解 next 数组。我们再来看下next[i]与extend[i]的定义:

  1. next[i]: T[i]…T[m - 1]与 T 的最长相同前缀长度;
  2. extend[i]: S[i]…S[n - 1]与 T 的最长相同前缀长度。

恍然大悟,求解next[i]的过程不就是 T 自己和自己的一个匹配过程嘛,下面直接看代码。

二.代码

#include <iostream>
#include <string>

using namespace std;

/* 求解 T 中 next[],注释参考 GetExtend() */
void GetNext(string & T, int & m, int next[])
{
   
    int a = 0, p = 0;
    next[0] = m;

    for (int i = 1; i < m; i++)
    {
   
        if (i >= p || i + next[i - a] >= p)
        {
   
            if (i >= p)
                p = i;

            while (p < m && T[p] == T[p - i])
                p++;

            next[i] = p - i;
            a = i;
        }
        else
            next[i] = next[i - a];
    }
}

/* 求解 extend[] */
void GetExtend(string & S, int & n
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值