kmp

KMP算法详解

﹥>﹥吖頭↗ 提交于 2020-01-28 21:02:15
  假如,A="abababaababacb",B="ababacb",我们来看看KMP是怎么工作的。我们用两个指针i和j分别表示,A[i-j+ 1..i]与B[1..j]完全相等。也就是说,i是不断增加的,随着i的增加j相应地变化,且j满足以A[i]结尾的长度为j的字符串正好匹配B串的前 j个字符(j当然越大越好),现在需要检验A[i+1]和B[j+1]的关系。当A[i+1]=B[j+1]时,i和j各加一;什么时候j=m了,我们就说B是A的子串(B串已经整完了),并且可以根据这时的i值算出匹配的位置。当A[i+1]<>B[j+1],KMP的策略是调整j的位置(减小j值)使得A[i-j+1..i]与B[1..j]保持匹配且新的B[j+1]恰好与A[i+1]匹配(从而使得i和j能继续增加)。我们看一看当 i=j=5时的情况。       i = 1 2 3 4 5 6 7 8 9 ……       A = a b a b a b a a b a b …       B = a b a b a c b       j = 1 2 3 4 5 6 7    此时,A[6]<>B[6]。这表明,此时j不能等于5了,我们要把j改成比它小的值j'。j'可能是多少呢?仔细想一下,我们发现,j'必须要使得B[1..j]中的头j'个字母和末j'个字母完全相等(这样j变成了j

洛谷P3375 【模板】KMP字符串匹配

China☆狼群 提交于 2020-01-28 04:56:49
题目传送门: 戳我进入 KMP算法是用来处理字符串匹配的问题的,也就是给你两个字符串,你需要回答B串是否是A串的子串,B串在A串中出现了几次,B串在A串中出现的位置等问题。 KMP算法的意义在于,如果你在洛谷上发了一些话,kkksc03就可以根据KMP算法查找你是否说了一些不和谐的字,并且屏蔽掉你的句子里的不和谐的话( 比如cxk鸡你太美就会被屏蔽成cxk**** ),还会根据你句子中出现不和谐的字眼的次数对你进行处罚 举个栗子:A:GCAKIOI B:GC ,那么我们称B串是A串的子串 我们称等待匹配的A串为主串,用来匹配的B串为模式串。 一般的朴素做法就是枚举B串的第一个字母在A串中出现的位置并判断是否适合,而这种做法的时间复杂度是O(mn)的,当你处理一篇较长文章的时候显然就会超时。 我们会发现在字符串匹配的过程中,绝大多数的尝试都会失败,那么有没有一种算法能够利用这些失败的信息呢? KMP算法就是 KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的 设主串(以下称为T) 设模式串(以下称为W) 用暴力算法匹配字符串过程中,我们会把T[0] 跟 W[0] 匹配,如果相同则匹配下一个字符,直到出现不相同的情况,此时我们会丢弃前面的匹配信息,然后把T[1] 跟 W[0]匹配,循环进行,直到主串结束,或者出现匹配成功的情况

KMP-单模式串匹配

◇◆丶佛笑我妖孽 提交于 2020-01-28 00:44:56
pat表示模式串,txt表示文本串,nex[i]表示pat中0~(i-1)最长相同前后缀。 KMP求pat在txt出现的次数或位置。 模式串的nex数组类似与ac自动机的fail指针,当发生不匹配时,跳到已匹配后缀最长的相同前缀的位置。求nex数组的过程就是pat自我匹配的过程。 学习链接:传送门   注意这个博客的预定约定和本文代码的约定不同 # include <iostream> # include <stdio.h> # include <string.h> using namespace std ; const int maxn = 1e6 + 7 ; char str [ maxn ] ; struct kmp { char pat [ maxn ] ; int pat_len ; int nex [ maxn ] ; void GetNext ( ) { int i = 0 , j = - 1 ; pat_len = strlen ( pat ) ; nex [ 0 ] = - 1 ; while ( i < pat_len ) { while ( j != - 1 && pat [ i ] != pat [ j ] ) j = nex [ j ] ; nex [ ++ i ] = ++ j ; } } int Count ( char * txt ) { //

KMP模板

走远了吗. 提交于 2020-01-26 23:53:21
参考: https://blog.csdn.net/qq_30241305/article/details/50700199 A.更正后模板代码,求子串最初出现位置 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int nexta[10005],a[1000005],s[10005]; 6 int n,m; 7 void getnexta(int s[])//初始next数组 8 { 9 memset(nexta,0,sizeof(nexta)); 10 int k = -1,j = 0; 11 nexta[0] = -1; 12 13 while(j <m)//这里的m为全局变量,为模式串长度 14 { 15 16 if(k == -1 || s[k] == s[j]) 17 { 18 nexta[j + 1] = k + 1; 19 j ++; 20 k ++; 21 } 22 else 23 { 24 k = nexta[k]; 25 } 26 } 27 28 } 29 int kmp(int s[],int t[])//t模式串,s母串 30 { 31 getnexta(t); 32 33 int i = 0,j = 0; 34 while(i

KMP算法

社会主义新天地 提交于 2020-01-26 20:18:04
参考链接:https://www.acwing.com/solution/acwing/content/2286/ 主串 是”ababaeaba”, 模式串 是”ababacd”,在暴力算法中,遇到不匹配的情况是这样处理的: main: "ababaeaba" // 例如这两个串,当sub为"ababae"时和"ababac"进行对 pattern: "ababacd" // 比,当main[i]为e时,发现和pattern[j]的值e不一致,暴力的做法是去下一个sub,即用"babaeab"和pattern进行比较。 暴力算法的code(时间复杂度O(N*M)) #include<iostream> using namespace std; const int N = 10010,M = 100010; int n,m; char p[N],s[M]; int ne[N]; int main() { cin >> n >> p+1 >> m >> s+1; // BF匹配过程 for(int i=1;i<=m;i++) { for (int j = 0,k=i; j <= n; ++j) { if (s[k] != p[j+1]) { break; }else { k++; } if (j+1==n) { // 匹配成功 printf("%d ",i-1); break; } }

【KMP】Power Strings

人走茶凉 提交于 2020-01-26 19:53:48
描述 Given two strings a and b we define a b to be their concatenation. For example, if a = “abc” and b = “def” then a b = “abcdef”. If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = “” (the empty string) and a^(n+1) = a*(a^n). 输入 Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case. 输出 For each s you should print the largest n such that s = a^n for some string a

KMP题目的解

吃可爱长大的小学妹 提交于 2020-01-26 09:45:51
浅谈KMP 这是我期末考试前复习的,并不推荐大家看我的整体学习KMP 这里推荐两个KMP分析透彻的网站 从头到尾彻底理解KMP(2014年8月22日版) kmp算法的位置在11话33:30,空降成功記得回來贊我 (严蔚敏老师的) 以下是个人理解KMP 1.1介绍KMP 我们学习其他的算法求子串在母串中的位置都会很麻烦,因为每次失配母串都要回溯到 i-j+2,并且简单算法(BM)算法整体的时间复杂度为 O(n*m) 但是用kmp算法就可以化解母串回溯这个问题,使得时间复杂度仅为O(m+n); 下面来说KMP 学习 KMP 的时候不要说为什么这样,要多想原来还可以这样 1.2一些概念 前缀 :指除了最后一个字符以外,一个字符串的全部头部组合; 后缀 :指除了第一个字符以外,一个字符串的全部尾部组合。 1.3步骤: 1>求最长前缀后缀; 这里都要给它写出来 ** 2求next值 ** 就是将得到的最大公共元素长度向后移一位加一 这里要一个一个写出来所有的浅醉和后缀 3求nextval 比如说这个我的,next[4]等于1,可我一看我的j[next[4]]还是个a,我从a到a变得没有意义,我就让next【4】=next【next【4】】= 1; 这就使nextval的含义,让比较次数更少。 来源: CSDN 作者: 西风下长安 链接: https://blog.csdn.net/qq

字符:BF与KMP

梦想与她 提交于 2020-01-23 13:34:07
字符串查找问题 给定文本串S和模式串W,从文本串S中找出模式串W第一次出现的位置 BF 从第一位字符开始,依次匹配,成功就返回,不成功就从第二个字符开始 KMP Knuth-Morris-Pratt字符串查找算法(简称为KMP算法)可在一个主文本字符串S内查找一个词W的出现位置,此算法通过运用对这个词在不匹配时本身就包含足够的信息来确定下一个匹配将在哪里开始的发现,从而避免重新检查先前匹配的字符 注:颜色相同就是匹配 那么如何找到某个字符前面串的最大相等子串来实现跳转呢 由next[j],表示第j个字符前的最大相等前缀和后缀的长度 第一个位置为next[0]=-1 接下来依照已知的next[j]=k求next[j+1] p[k]==p[j], next[j+1]=next[j]+1结束 p[k] !=p[j],记h=next[k]递归上面步骤 KMP改进 上面的next数组依然有缺陷,下图改进前(左侧),明显跳转k的时候明显不能匹配,因为w[j]=w[k],我们希望直接跳转t处(右侧) 我们可以在求next的时候假如断w[j]==w[k]:next[j]=next[k],因为从一开始本身建立在不相等基础上,所以只要找前面一个 BM 移动字符数是通过两条规则决定的:坏字符规则和好后缀规则。实际移动为通过这两条规则计算出的最大移动个数。 坏字符规则:

POJ 3461 Oulipo (KMP)

ⅰ亾dé卋堺 提交于 2020-01-22 23:57:41
传送门 题目大意 有n次询问,问W串在T串中出现的次数 题解 KMP 代码 #include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,lenw,lent,nxt[10009]; char w[10009],t[1000009]; void getnext(){ for(int i=2,j=0;i<=lenw;i++){ while(w[i]!=w[j+1]&&j)j=nxt[j]; if(w[i]==w[j+1])nxt[i]=++j; } } int kmp(){ int js=0; for(int i=1,j=0;i<=lent;i++){ while(t[i]!=w[j+1]&&j)j=nxt[j]; if(t[i]==w[j+1])j++; if(j==lenw){js++;j=nxt[lenw];} } return js; } int main(){ scanf("%d",&n); while(n--){ scanf("%s\n%s",w+1,t+1); lenw=strlen(w+1);lent=strlen(t+1); getnext(); printf("%d\n",kmp()); } return 0; } 来源: https://www.cnblogs

831. KMP字符串(模板)

老子叫甜甜 提交于 2020-01-22 21:06:56
给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。 模板串P在模式串S中多次作为子串出现。 求出模板串P在模式串S中所有出现的位置的起始下标。 输入格式 第一行输入整数N,表示字符串P的长度。 第二行输入字符串P。 第三行输入整数M,表示字符串S的长度。 第四行输入字符串S。 输出格式 共一行,输出所有出现位置的起始下标(下标从0开始计数),整数之间用空格隔开。 数据范围 1 ≤ N ≤ 10 4 1≤N≤104 1 ≤ M ≤ 10 5 1≤M≤105 输入样例: 3 aba 5 ababa 输出样例: 0 2代码: import java.util.Scanner; public class Main{ static int m,n;//n为子串,m为父串 static int ne[]=new int[10005]; static char p[]=new char[10005]; static char s[]=new char[100005]; static void get_next(){ for(int i=2,j=0;i<=n;i++){//i从2开始,如果i=1就不匹配,那么ne[1]=0 while(j>0 &&p[i]!=p[j+1]) j=ne[j]; if(p[i]==p[j+1]) j++; ne[i]=j; } }