匹配字符串的KMP算法

其中next序列,表示子串的前后缀最大匹配长度. 例如对于字符串C[], next[i]表示子串c[0 .. i]中, 前缀与后缀的最大匹配长度.

举例如果子串是 abcuab, 其前缀是a, ab, abc, abcu, abcua, 后缀是 b, ab, uab, cuab, bcuab, 其中匹配的最大子串是ab, 长度是2.

按定义挨个计算next的值

    public static int[] getNexts(char[] tt)
    {
        int[] nexts = new int[tt.length];
        nexts[0] = 0;
        // 从1到结束, 挨个计算next
        for (int i = 1; i < tt.length; i++)
        {
            // 在给定的子串里, 记录matched时, 最大的长度值
            for (int j = 0; j < i; j++)
            {
                boolean matched = true;
                // 使用 k, 依次比较从 0  到 j 和从 i-j 到  i的字符是否相等, 注意下标都是从小往大移动
                for (int k = 0; k <= j; k++)
                {
                    if (tt[k] != tt[i-j+k])
                    {
                        matched = false;
                        break;
                    }
                }

                // 匹配的, 记录最大长度
                if (matched)
                {
                    int length = j + 1;
                    if (nexts[i] < length)
                        nexts[i] = length;
                }
            }
        }

        return nexts;
    }

改进后的方法, 在遍历中依次记录next的值, 令循环减少许多

    /**
     * 只使用两个起始下标, 来计算和记录next序列
     *
     * @param tt
     * @return
     */
    public static int[] getNexts2(char[] tt)
    {
        int[] nexts = new int[tt.length];

        nexts[0] = 0;
        // 前缀起始下标
        int prefix = 0;
        // 后缀起始下标
        int suffix = prefix + 1;
        // 匹配长度
        int len = 0;
        while(suffix < tt.length)
        {
            if (tt[prefix] == tt[suffix])
            {
                // 如果匹配, 则记录下当前的next最大值, 并且将前缀和后缀下标都往大移动一位
                prefix++;
                len++;
                if (nexts[suffix] < len)
                    nexts[suffix] = len;
            }
            else
            {
                // 如果不匹配, 则当前长度归零, 并且前缀回归起点, 而后缀依然往后走
                len = 0;
                prefix = 0;
            }
            suffix++;
        }

        return nexts;
    }
时间: 2024-12-14 03:59:16

匹配字符串的KMP算法的相关文章

字符串的KMP算法替换

1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 6 7 class myString 8 { 9 private: 10 string mainstr; 11 int size; 12 void GetNext(string p,int next[]); 13 int KMPFind(string p,int next[]); 14 public: 15 myString(); 16 //~myS

字符串匹配算法KMP算法

数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多多余的不符合的匹配做了冗余的比较.假设源字符串长n,字串长m 该算法最差时间复杂度为 m*(n-m+1),记为O(n*m);这里不做过多解释朴素匹配算法. KMP算法: kmp算法不是在源字符串中下手,他是从字串下手,比如我要在源字符串(acabaabaabcacaabc)中匹配一个字符串字串(ab

字符串模式匹配KMP算法中的next数组算法及C++实现

一.问题描述: 对于两个字符串S.T,找到T在S中第一次出现的起始位置,若T未在S中出现,则返回-1. 二.输入描述: 两个字符串S.T. 三.输出描述: 字符串T在S中第一次出现的起始位置,若未出现,则返回-1. 四.输入例子: ababaababcbababc 五.输出例子: 5 六.KMP算法解析: KMP算法分为两步,第一步是计算next数组,第二步是根据next数组通过较节省的方式回溯来比较两个字符串. 网络上不同文章关于next数组的角标含义略有差别,这里取参考文献中王红梅<数据结构

字符串匹配算法——KMP算法

1.字符串匹配 字符串匹配是计算机的基本任务之一. 字符串匹配是什么?举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一.它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth(<计算机程序设计艺术>的作者). 2.KMP算法 这个算法不太容易理解,网上有很多解释,但

字符串查找KMP算法(转)

如果你用过ctrl+F这个快捷键,那么你有很大的概率使用过这个算法,这就是在待查找字符串(可能有成千上万个字符)中找出模式串(比较小,可能有几个字符),可能找到大于或者等于1次的位置.例如,在ababcd中找出abc.这里介绍算法思想,只给出了第一次出现的位置. 一.算法思想 传统算法是从匹配串第一字符开始和模式串比较,直到遇到不符合的字符,然后从匹配串的下一个字符开始,重复上面的过程.代码如下: void find(char t[],char p[]){ int m = strlen(t);

字符串查找KMP算法

如果你用过ctrl+F这个快捷键,那么你有很大的概率使用过这个算法,这就是在待查找字符串(可能有成千上万个字符)中找出模式串(比较小,可能有几个字符),可能找到大于或者等于1次的位置.例如,在ababcd中找出abc.这里介绍算法思想,只给出了第一次出现的位置. 一.算法思想 传统算法是从匹配串第一字符开始和模式串比较,直到遇到不符合的字符,然后从匹配串的下一个字符开始,重复上面的过程.代码如下: void find(char t[],char p[]){ int m = strlen(t);

字符串匹配算法-kmp算法

一原理: 部分转自:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一.它以三个发

查找字符串的 KMP 算法

查找字符串是我们平常编程过程中经常遇到的,现在介绍一种查找字符串算法,增加程序的执行速度. 通常我们是这么写的: /* content: search a string in a othor string author: lw date: 2015-01-30 target: kmp algorithm */ #include <stdio.h> #include <string.h> void compare(char * sourcestr, char * targetstr)

HDU-1358 Period 字符串问题 KMP算法 求最小循环节

题目链接:https://cn.vjudge.net/problem/HDU-1358 题意 给一个字符串,对下标大于2的元素,问有几个最小循环节 思路 对每个元素求一下minloop,模一下就好 提交过程 TLE maxn没给够 AC 代码 #include <cstring> #include <cstdio> const int maxm=1e6+20; char P[maxm]; int fail[maxm]; void getFail(int m){ fail[0]=fa