首页 > 其他分享 >KMP

KMP

时间:2023-12-08 19:14:01浏览次数:20  
标签:cn int next ++ length KMP String

简介

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。

实现

构造 next[] 数组

  • 前缀:除最后一个字符外,字符串的所有头部子串
  • 后缀:除第一个字符外,字符串的所有尾部子串
  • 前后缀相等的最大长度:\(\{a, ab, aba\} \cap \{b, ab, bab\}=\{ab\}\)
  • next[i]:模式串 s[0...i-1] 的相等前后缀的最大长度
字串 前缀 后缀 相等前后缀的最大长度
"" \(\phi\) \(\phi\) next[0] = -1
"a" {} {} next[1] = 0
"ab" next[2] = 0
"aba" next[3] = 1
"abab" next[4] = 2

匹配

求解 next[] 数组

代码

public class Solution
{
    public static void solution(String s1, String s2)
    {
        ArrayList<Integer> ans = new ArrayList<>();
        int[] next = getNext(s2);
        int i = 0, j = 0;
        while (i < s1.length())
        {
            if (s1.charAt(i) == s2.charAt(j))
            {
                i++;
                j++;
            }
            else if (next[j] == -1) i++;
            else j = next[j];
            if (j == s2.length())
            {
                ans.add(i - j);
                j = 0;
            }
        }
        if (!ans.isEmpty())
            System.out.println(ans.stream().map(String::valueOf).collect(Collectors.joining(" ")));
        else
            System.out.println(-1);
    }

    public static int[] getNext(String s)
    {
        if (s.length() == 1) return new int[]{-1};
        int[] next = new int[s.length()];
        int pos = 2, cn = 0;
        next[0] = -1;
        next[1] = 0;
        while (pos < s.length())
        {
            if (s.charAt(pos - 1) == s.charAt(cn))
                next[pos++] = ++cn;
            else if (cn > 0)
                cn = next[cn];
            else
                next[pos++] = 0;
        }
        return next;
    }

    public static void main(String[] args)
    {
        solution("ababcabaababac", "ababa");
    }
}

标签:cn,int,next,++,length,KMP,String
From: https://www.cnblogs.com/VividBinGo/p/17888853.html

相关文章

  • 关于kmp模板
    那个求p串的next数组这个版本是下标从1开始的字符串,如果从0开始的话,可以在前面加空字符,然后p.size或者s.size的地方-1即可。nex[1]=0    for(inti=2,j=0;i<=p.size();i++){if(j&&p[i]!=p[j+1])j=nex[j];if(p[i]==p[j+1])j++;nex[i]=j;} kmp函数......
  • AcWing 831. KMP字符串
    题面:给定一个字符串S,以及一个模式串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。模式串P在字符串S中多次作为子串出现。求出模式串P在字符串S中所有出现的位置的起始下标。原题链接:831.KMP字符串-AcWing核心:next数组-最长相等前后缀next[i]存储......
  • KMP字符串匹配算法 整理
    KMP整理题面视频详解KMP的作用KMP算法的主要作用是求出一个字符串(模式串)是否为另一个字符串(主串)的子串,并同时求出它出现的位置,也即字符串匹配问题。算法解析暴力先说暴力算法:从头开始枚举模式串位置的起点,然后遍历从起点往后\(m\)个字符,检查它是否与模式串完全相同......
  • KMP
    一、算法描述本篇文章水平不够,讲不清楚KMP到底是怎么回事,以后再更新一下。本篇文章讲述的是KMP算法,一个著名的字符串匹配算法,效率很高,\(O(n)\)的时间复杂度。难点在于:如何理解\(next[i]\)★★★\(ne[i]=j\)表示,\(p[1~j]=p[i-j+1,i]\),从\(1\)到\(j\)的前缀......
  • P3375 【模板】KMP( 普及/提高− ) 题解
    题目传送门思路:首先我们要学习一下\(KMP\)算法,不会的可以看这个大佬的文章那么我们就直接开始讲思路了。针对于每一位,\(kmp\)算法已经预处理出了一个对应\(kmp\)数组的单元,映射着如果此位失配,它可能的最靠后的一个重新开头是哪一个。让我们举一个例子:假如让\(aaab\)与......
  • KMP算法
    #include<iostream>usingnamespacestd;int*getNext(stringpattern){int*next=(int*)malloc(sizeof(int)*pattern.size());if(next==NULL){returnNULL;}next[0]=-1;intj=-1;for(inti=1;i<p......
  • KMP板子
    updateon2023.11.17NOIP前来复习板子,发现KMP整理的不是很到位,所以更新详细一些。模板题抽象的blog浅显易懂的讲解视频:(dalao讲得太好了\(%%%\))备用网址\(kmp\)(字符串匹配)的概念:主串:被匹配的字符串模式串:匹配的串最长前后缀:一个字符串某个前缀后后缀相同,而且长度尽可......
  • KMP与自动机
    KMP与AC自动机都是字符串匹配KMP是单模匹配ac自动机是多模匹配KMP原理例子当我们匹配字符串A(长度为n)中是否有B(长度为m,m<n)的时候比如:AABCDABCDEFBABCDE一个朴素的思路是暴力,复杂度当然是O(n*m)KMP就是一个优化的算法KMP的理论基础就是,并不是每次匹......
  • KMP模板
    #include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constintN=1e3+10,inf=0x3f3f3f3f;intnex[N];//nex[j]的意思是当子串的第j个字符和主串的第i个字符不匹配时,我们应该从子串的nex[j]字符开始重新匹配stringa,b;/*kmp指针回退j=nex[j-1]......
  • 扩展 KMP——Z 函数
    本文下标从\(0\)开始。建议:前置知识。扩展KMP(Z函数)我们已经认识了前缀函数了。它是维护一个字符串的所有前缀的最长公共真前后缀的长度——\[\overbrace{s_0\dotss_{\pi(i)-1}}~s_{\pi(i)}\dotss_{i-\pi(i)}~\overbrace{s_{i-\pi(i)+1}\dots\color{red}s_i}~s_{i+1}......