kmp算法

KMP算法

痞子三分冷 提交于 2020-03-23 18:23:53
#include<stdio.h> #include<string.h> void sstring(chara,charb)//将一个字符串整体后移一个单位方便后续计算 { int len,i; a[0]=strlen(b); for(i=1;i<=a[0];i++) a[i]=b[i-1]; return; } void get_next(char T,int next) //next函数求法运用了递推的思想,即从广义的某个字符t[i]开始推出普遍规律 其中又再次运用了kmp思想 { int i=1,j=0; next[1]=0; while(i<T[0]) 欧元符号http://www.gendan5.com/currency/EUR.html if(j==0||T[i]==T[j])//j=0意味着无相同前后缀,模式串从首位开始重新与主串匹配 { ++i; ++j; next[i]=j; //这三步可以直接写成 next[++i]=++j; } else j=next[j];//仍然不匹配 模式串右滑 } / void get_next(char T,int next) { int i=1,j=0; next[1]=0; while(i<T[0]) if(T[i]= =T[j]) { ++i; ++j; next[i]=j; } else if(j==0) /

KMP算法

不打扰是莪最后的温柔 提交于 2020-03-17 14:42:56
KMP算法 一个专门匹配字符串的算法 e,g 先给出一个 待匹配字符串 B a b a a b b a b a a b 0 0 1 1 2 0 1 2 3 4 5 // 从 2 个字母开始进行匹配,第一个的F数组值,默认为 0,m 即字符串长度 for(int i = 1; i < m; i++) { // j 可以代表将与 B[i] 进行比较的 下标 int j = F[i - 1] // 当 不匹配 且 待匹配下标对应的数字的 F数组值还大于 1的情况下,进行 j 的前进 // 直到 B[i] 与 B[j] 相等 或者 到了 无对称字母位置 // 例如 aba 中的 b处 此时 j = 0,而j = 0 对应的就是 首字母a,相当于重新开始 while(B[i] != B[j] && j >= 1) { j = F[j - 1]; } // 如果进一步的还继续匹配 if(B[i] == B[j]) F[i] = j + 1; // 下标数组 + 1 else // 否则 归零 F[i] = 0; } 利用 F数组寻找匹配,每找到一个匹配就输出其开始的位置 // i 是对应 匹配字符串 A 中的 下标,前进 while(i < n) { // 如果 相匹配 if(A[i] == B[j]) { i++; j++; // j 到头了,代表相匹配了,此段 if(j == m) { /

面试基础:KMP字符串查找算法

故事扮演 提交于 2020-03-13 16:38:33
字符串的一种基本操作是子字符串查找:给定一端长度为N的文本字符串text和一个长度为M(M<N)的模式字符串pattern,在文本字符串中查找和该模式字符串相同的子字符串。 在这互联网时代,字符串查找的需求在很多情景都需要,如在文本编辑器或浏览器查找某个单词、在通信内容中截取感兴趣的模式文本等等。 子字符串查找最简单的实现肯定是暴力查找: public static int search(String text, String pattern) { int N = text.length(); int M = pattern.length(); for (int i = 0; i < N-M; i++) { int j; for (j = 0; j < M; j++) { if (text.charAt(i+j) != pattern.charAt(j)) break; } if (j == M) return i; } return -1; } 可以看到,暴力查找的最坏时间复杂度为O(N*M),实际应用中往往文本字符串很长(成万上亿个字符),而模式字符串很短,这样暴力算法的时间复杂度是无法接受的。 为了改进查找时间,人们发明了很多字符串查找算法,而今天的主角KMP算法(D.E.Knuth,J.H.Morris和V.R.Pratt发明,简称KMP算法)就是其中的一种。

BF算法与KMP算法(字符串匹配算法)

折月煮酒 提交于 2020-02-29 11:18:32
BF算法 BF算法,简称暴力破解 Bruce Force ,又称朴素模式的匹配算法。 可以看出BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配, 若相等,则继续比较S的第二个字符和T的第二个字符; 若不相等,则比较S的第二个字符和T的第一个字符,依次比较,直到得出最后的匹配结果。 这种算法的比较很暴力,由于产生了多次的回溯,在效率上存在很大的缺陷。 时间复杂度O(m*n) 代码: 1 package bf; 2 3 public class Test { 4 public static void main(String[] args) { 5 String bf = "IloveChinveChia"; 6 String pattern = "veChi"; 7 int m = bf.length(); // i 8 int n = pattern.length(); // j 9 int i = 0, j = 0; 10 while (i < m) { 11 if (bf.charAt(i) == pattern.charAt(j)) { // 一一匹配时 12 i++; 13 j++; 14 } else { 15 i = i - j + 1; 16 j = 0; 17 } 18 if (i == m) 19 break; 20 if (bf.charAt

串的模式匹配 : KMP算法

巧了我就是萌 提交于 2020-02-28 21:09:03
当存在 [1] 这样的现象,[2] 这样的做法,是否合理以及正确,或者有 [1] 这样的现象,为什么就可以有 [2] 这样的做法 ? 算法思想 [1] 当主串的 第i个字符与子串的第j个字符失配时 ,若子串的 前(k-1)个字符 和子串的 后(k-1)个字符 匹配, ‘p 1 ……p k-1 ’=‘p j-k+1 ……p j-1 ’ ,则只需主串 S 的第 i 个字符与子串 P 的第 k 个字符开始向后比较即可,i 不必回溯。 [2] k的值只与子串的组成有关,而与主串无关,即 k 值与 j 失配位置之前的子串的结构相关,每一个 j 位置对应一个k值,用next[j]存储,表示 当模式串中第 j 个字符与主串中第 i 个字符失配时 ( S i ≠ P j ) , 下一次模式串 P 中第next[j]个字符与主串 S 的第i个字符比较 。 简而言之 若子串中,‘p 1 ……p k-1 ’=‘p j-k+1 ……p j-1 ’,则在 j 处的失配,i 不回溯,直接和子串的 k 位置比较即可,k位置用 next[j] 存储。 问题提出 其实,算法思想中[1]是 现象 ,也就是子串中需要存在这样的前后缀相等时,[2]是 做法 ,表示在失配的位置 j ,模式串应该向右滑动 k 距离。那么当存在这样的现象,这样的做法,是否合理以及正确?或者有 [1] 这样的现象,为什么就可以有 [2]

KMP算法求循环节,为什么能求循环节

本秂侑毒 提交于 2020-02-28 03:50:20
众所周知,KMP算法可以求最小循环节,为什么可以求循环节呢? 博主之前对KMP算法的理解不够深入,最近突然又想起来了,就深入研究了一下。 KMP算法中最重要的就是next数组,next[i]表示是字符串中所有以 i 为结尾的非前缀子串中与前缀能匹配的长度的最大值。可能有点绕,缕一缕吧,这就是next[ ]数组的定义而已。 我们求最小循环节也是利用next[ ]数组求的。假设字符串是一个循环字符串,可以有一个循环节循环多次得到(假设多于一次),不妨假设循环节是 str1 ,原来的字符串肯定是由循环节循环而来,即 string=str1str1...str1 ,如果字符串长度为len,根据next[ ]数组的定义,next[len]就是以字符串结尾为结尾的非前缀与前缀匹配的最大长度,如果这个字符串能由一个循环节循环多次得到,那么next[n]中一定包含了至少一次循环节,而且是去掉了从头开始的第一个循环节后的整个字符串。自己在本子上画一下就好了。对齐方式肯定是下图这个样子,每一个方框都是一个循环节。 因为我们设的是最小循环节,如果认为有其他方法,那么一定可以将第二个字符串对齐的时候向前移动,如果这样的话那么它肯定不是最小循环节。既然这样,最小循环节长度就是 len - next[len] ,如果能由它循环多次得来,一定满足满足以下条件。 len % ( len - next[len] )

《算法》笔记 15

拜拜、爱过 提交于 2020-02-27 08:10:22
暴力子字符串查找算法 隐式回退 性能 显式回退 Knuth-Morris-Pratt算法 确定有限状态自动机 DFA的构造 性能 Boyer-Moore算法 跳跃表的构建 性能 Rabin-Karp指纹字符串算法 关键思想 Horner方法 性能 字符串的一种基本操作就是子字符串查找。比如在文本编辑器或是浏览器中查找某个单词时,就是在查找子字符串。子字符串的长度(可能为100或1000)相对于整个文本的长度(可能为100万甚至是10亿)来说一般是很短的,在如此多的字符中找到匹配的模式是一个很大的挑战,为此计算机科学家们发明了多种有趣、经典且高效的算法。 ### 暴力子字符串查找算法 要解决这个问题,首先想到的是暴力查找的方法,在文本中模式可能出现匹配的任何地方检查是否匹配。 #### 隐式回退 首先是隐式回退的实现方式,之所以叫隐式回退,在与显式回退的实现对比后就明白原因了。 public static int search(String pat, String txt) { int patL = pat.length(); int txtL = txt.length(); for (int i = 0; i <= txtL - patL; i++) { int j; for (j = 0; j < patL; j++) if (txt.charAt(i + j) != pat

KMP

风流意气都作罢 提交于 2020-02-25 01:45:17
KMP算法基本流程 核心思路:寻找回溯位置 其实便是众所皆知的使用next数组,通过next数组的保存p前后缀的交集的最大长度 例如:给定一个Pattern:abedabexa 默认index为0的位置的next值为0,由于下标i和j所对应的字符不同,i保存不变,j下标next值为0,j向后移一位 由于下标i和j所对应的字符不同,i保存不变,j下标next值为0,j向后移一位 由于下标i和j所对应的字符不同,i保存不变,j下标next值为0,j向后移一位 下标i和j对应字符相同,i,j同时向后移动一位,j下标的next值为i下标的next值+1 注意:下标j-1对应的next值为1,说明了,j下标前已有前缀和后缀重复的字符串,其长度为1,那么j的next值则赋为(j-1)下标的next值+1 重复上述思路 到了这里,出现了字符不匹配,那么该怎么办呢? 解决:下标i移至下标(i-1)所对应的next值,并继续匹配i和j所对应的字符 由于i与j所对应字符不相同,且i无法再继续向前移动,那么j的next值则赋为i的next值 由于下标i已经为0 若i与j所对应字符不匹配,i无法继续向前移动只能将j对于next值赋为i的next值 若i与j所对应字符相匹配,则j对应的next值则赋为i的next值+ 1 j下标超出数组最大下标,完成next数组的构造 代码实现 #include

字符串模式匹配KMP算法

拥有回忆 提交于 2020-02-21 17:02:10
字符串模式匹配指的是,找出特定的模式串在一个较长的字符串中出现的位置。 朴素的模式匹配算法 很直观的可以写出下面的代码,来找出模式串在一个长字符串中出现的位置。 1: /* 2: 朴素的模式匹配算法 3: 功能:字符串的模式匹配 4: 参数: 5: s:目标串 6: p:模式串 7: pos:开发匹配的位置 8: 返回值: 9: 匹配成功,返回模式串在目标串的其实位置 10: 匹配不成功,返回-1 11: */ 12: int match(const char * s ,const char * p,int pos){ 13: int i = pos ; 14: int j= 0 ; 15: while(s[i] != '\0' && p[j] != '\0') { 16: if(s[i] == p[j]) { 17: i ++ ; 18: j ++ ; 19: }else { 20: i = i - j + 1; 21: j = 0 ; 22: } 23: } 24: 25: if(p[j] == '\0') 26: return i - j ; 27: else 28: return -1 ; 29: } 上面的代码,s就是目标串,p是模式串,pos指定从s的什么位置开始匹配p。其实现思想也很简单: 当s[i] == p[j]时,目标串和模式串的指针都向后移动一位,进行匹配

数据结构与算法整理3——BP算法和KMP算法

核能气质少年 提交于 2020-02-13 17:12:01
数据结构与算法整理3——BP算法和KMP算法 目录 数据结构与算法整理3——BP算法和KMP算法 1、字符串的基本操作 2、模式匹配——BP算法和KMP算法 3、串的操作代码(C语言) 1、字符串的基本操作 1)串的定义:字符串(也就是串)是0个或多个字符序列组成的有限序列。 串就是数据元素为单个字符的特殊线性表。 “qhjkdcbjsb”(隐含结束符\0)就是一个字符串,引号起界定作用,“”表示空串,串长为0 “ ”空格串不是空串,串长为空格数。 2)串的存储类型: 顺序存储 :定长顺序存储结构、堆分配存储结构(动态分配连续内存) 链式存储: 2、模式匹配——BP算法和KMP算法 串的模式匹配:就是指定一个主串S和子串T,求T在S中第一次出现的位置。 (1) 朴素模式匹配(BP算法) 核心思想 :主串S和子串T,S[1]和T[1]比较,S[2]与T[2]比较,直到S[n]与T[n]都是相等的为止,若S[i]与T[i]不相等,则子串向右移动一个(一个字符)继续比较。 时间复杂度 :主串S长度为n,子串T长度为m,最多进行m(m-n+1)次,最坏的时间复杂度为O(mn) 效率不高。 (2) KMP 算法 核心思想 :尽量利用已经得到的“部分匹配”的结果信息,不要让i回溯,加快子串右滑的速度, 问题由子串决定而不是主串决定的 next 数组 :是一个智能数组