kmp算法

KMP算法

僤鯓⒐⒋嵵緔 提交于 2020-02-11 23:35:29
简单模式匹配算法 对于一个串中某子串的定位操作称为模式匹配 int i=1,j=1,k=i; //从主串和模式串第一个位置开始遍历 while(i <= s_length && j <= t_length){ if(s[i]==t[j]){//如果相等,则都向后进一位 ++i; ++j; } else{ //如果不相等,则 i 回溯到下一位,j 回溯到模式串第一位,重新依次比较 j=1; i=++k; //或写为i=i-j+2; } } if(j > t_length)cout<<k<<endl; else cout<<"NO"<<endl; KMP算法 简单模式匹配算法需要不断回溯主串和子串,但是KMP算法只需要回溯字串,这就是它更快的原因 原来需要将子串回溯到下标为1,将主串回溯到下一位,KMP算法只需要将子串下标 j 回溯到 next[j] 的位置,所以 求next数组 就是它的核心 出现了几个个问题: 1.next数组存的是什么? 为什么只用将子串下标 j 回溯到 next[j]的位置就能达到我们想要的效果? 2.怎么求next数组。 1.next[j]数组存的是如果主串和子串失配,j要回溯的那个位置 如图,如果按照原来的方法,主串和子串都需要回溯比较,但是我们发现有一些比较其实是可以省略的,观察图中,发现 a. 比较下标前面的子串完全匹配。 b.

Java实现KMP算法

﹥>﹥吖頭↗ 提交于 2020-02-07 09:16:12
转自:http://blog.csdn.net/tkd03072010/article/details/6824326 —————————————————————————————————— package arithmetic; /** * Java实现KMP算法 * * 思想:每当一趟匹配过程中出现字符比较不等,不需要回溯i指针, * 而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远 * 的一段距离后,继续进行比较。 * * 时间复杂度O(n+m) * * @author xqh * */ public class KMPTest { public static void main(String[] args) { String s = "abbabbbbcab"; // 主串 String t = "bbcab"; // 模式串 char[] ss = s.toCharArray(); char[] tt = t.toCharArray(); System.out.println(KMP_Index(ss, tt)); // KMP匹配字符串 } /** * 获得字符串的next函数值 * * @param t * 字符串 * @return next函数值 */ public static int[] next( char[] t) { int[] next =

扩展KMP算法的详细理解+例题--hdu 2328

妖精的绣舞 提交于 2020-02-03 04:51:50
借鉴博客: https://blog.csdn.net/qq_40160605/article/details/80407554 扩展KMP的详细理解 扩展KMP求的是对于原串S1的每一个后缀子串与模式串S2的最长公共前缀。它有一个next[]数组和一个extend[]数组。 next[i]表示为模式串S2中以i为起点的后缀字符串和模式串S2的最长公共前缀长度. 其中,next[0]=l2; next[i]=max{ k|i<=i+k-1<l2 &&S2.substring(i,i+k-1) == S2.substring(0,k-1) } 其中str.substring(i, j)表示str从位置i到位置j的子串,如果i>j则,substring为空。 extend[i]表示为以字符串S1中以i为起点的后缀字符串和模式串S2的最长公共前缀长度. 下面我们先以一组样例来理解扩展KMP的过程 (1) 第一步,我们先对原串S1和模式串S2进行逐一匹配,直到发生不配对的情况。我们可以看到,S1[0]=S2[0],S1[1]=S2[1],S1[2]=S2[2],S1[3] ≠S2[3],此时匹配失败,第一步结束,我们得到S1[0,2]=S2[0,2],即extend[0]=3; (2) Extend[0]的计算如第一步所示,那么extend[1]的计算是否也要从原串S1的1位置

KMP

£可爱£侵袭症+ 提交于 2020-02-01 23:49:01
KMP(Knuth-Morris-Pratt)算法是一种改良的字符串匹配算法,在朴素算法的基础上增加了“记忆”功能,在匹配失败时会考虑已匹配的字符串从而进行跳步以缩减时间复杂度至$O(n+m)$。 T:文本串 P:模式串 f[i]:P的前i长度(0 ~ i-1)子串中前后相等的最大长度 int f[100]; void getFail(string P) { int m = P.length(); for(int i = 1; i < m; i++) { int j = f[i]; while(j && P[i] != P[j]) j = f[j]; f[i + 1] = P[i] == P[j] ? j + 1 : 0; } } void find(string T, string P) { int n = T.length(), m = P.length(); getFail(P); int j = 0; for(int i = 0; i < n; i++) { while(j && T[i] != P[j]) j = f[j]; if(T[i] == P[j]) j++; if(j == m) cout << i - m + 1 << endl; } } 来源: https://www.cnblogs.com/nioh/p/12250655.html

BF算法、KMP算法及思想

回眸只為那壹抹淺笑 提交于 2020-01-31 08:38:34
BF算法 当我们在进行字符串匹配时,我们会把主串和模式串,从某个位置,我们记为【pos】,开始匹配,每匹配成功一个字符,就让 i 加一。可一旦“失配”,我们就会让i回溯,从pos的下一个字符开始,重新执行上面的过程,直到模式串被匹配完。 int Index_BF ( string str1 , string str2 , int pos = 1 ) { int i = pos , j = 1 ; while ( i < str1 . length ( ) && j < str2 . length ( ) ) { if ( str1 [ i ] == str2 [ j ] ) { i ++ ; j ++ ; } else { pos ++ ; i = pos ; j = 1 ; } } if ( j == str2 . length ( ) ) return i - j + 1 ; else return 0 ; } KMP算法 KMP算法的精髓所在,就是当“失配”时,不需要将i重新回溯到pos的下一个。 而是将模式串向右滑行,尽可能远的距离。因为在模式串中,当“失配”时,如果当前“失配”字符的前k个字符,和模式串的最开始的k个字符,如果相等,那么这k个字符,是不需要再进行比较的,直接让主串的第i个字符,和模式串的第k+1个字符开始比较就可以了。 比如当我们比较 i从8到15

kmp算法---简单易懂

匆匆过客 提交于 2020-01-30 01:51:46
KMP字符串 给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。 模板串P在模式串S中多次作为子串出现。 求出模板串P在模式串S中 所有 出现的位置的起始下标。 输入格式 第一行输入整数N,表示字符串P的长度。 第二行输入字符串P。 第三行输入整数M,表示字符串S的长度。 第四行输入字符串S。 输出格式 共一行,输出所有出现位置的起始下标( 下标从0开始计数 ),整数之间用空格隔开。 数据范围 1 ≤ N ≤ 10 4 1 ≤ M ≤ 10 5 输入样例: 3 aba 5 ababa 输出样例: 0 2 # include <iostream> using namespace std ; const int N = 10010 , M = 100010 ; //定义两个常量 int main ( ) { int n , m ; //分别是 p, s串的长度 char p [ N ] , s [ M ] ; //定义两个字符数组 p是模板串(短),s是模式串(长) int next [ N ] ; //该数组考虑的是当前字符最大相同前缀后缀 cin >> n >> p + 1 >> m >> s + 1 ; //输入整数和字符串 //求next数组 next [ 1 ] = 0 ; //这里的next数组下标从 1开始 for ( int i = 2

KMP算法实现查找字符串第一次出现的位置

一世执手 提交于 2020-01-27 01:18:23
package ten_algorithm . kmp ; import ten_algorithm . dynamic . KnapSack ; import java . util . Arrays ; /** * Author:jinpma * Date :2019/12/28 */ public class KmpSearch { public static void main ( String [ ] args ) { String str1 = "BBC ABCDAB ABCDABCDABDE" ; String str2 = "ABCDABD" ; KmpSearch k = new KmpSearch ( ) ; int [ ] next = k . next ( str2 ) ; int index = k . findIndex ( str1 , str2 , next ) ; System . out . println ( index ) ; } private int findIndex ( String str1 , String str2 , int [ ] next ) { int i , j ; for ( i = 0 , j = 0 ; i < str1 . length ( ) ; i ++ ) { if ( str1 . charAt ( i

KMP算法视频推荐

夙愿已清 提交于 2020-01-25 18:36:02
KMP算法讲解 b站正月点灯笼版本 这个讲解的很深入浅出 三哥版本 这个讲的也不错,用的字符串例子也上面一个复杂一点 如果看不懂可以看第一个,再看第二个 总结:KMP算法比暴力算法,能更快地找到目标字符串,主要是因为前缀表的创造 只要理解好公共前后缀,以及如何使用,就能明白KMP算法为什么比暴力算法要快的原因了 来源: CSDN 作者: c20171118 链接: https://blog.csdn.net/c20171118/article/details/103968611

KMP算法

a 夏天 提交于 2020-01-23 21:34:54
KMP算法 给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。 模板串P在模式串S中多次作为子串出现。 求出模板串P在模式串S中所有出现的位置的起始下标。 输入格式 第一行输入整数N,表示字符串P的长度。 第二行输入字符串P。 第三行输入整数M,表示字符串S的长度。 第四行输入字符串S。 输出格式 共一行,输出所有出现位置的起始下标(下标从0开始计数),整数之间用空格隔开。 数据范围 1≤N≤104 1≤M≤105 输入样例: 3 aba 5 ababa 输出样例: 0 2 代码: # include <iostream> using namespace std ; const int N = 10010 , M = 100010 ; int n , m ; int ne [ N ] ; char s [ M ] , p [ N ] ; int main ( ) { cin >> n >> p + 1 >> m >> s + 1 ; for ( int i = 2 , j = 0 ; i <= n ; i ++ ) { while ( j && p [ i ] != p [ j + 1 ] ) j = ne [ j ] ; if ( p [ i ] == p [ j + 1 ] ) j ++ ; ne [ i ] = j ; } for ( int

字符串匹配——KMP算法

Deadly 提交于 2020-01-19 03:26:10
KMP算法 【*注】转载来源:[(https://www.cnblogs.com/SYCstudio/p/7194315.html)] 【膜拜原作者大大,文章转载,补充了字符串匹配的完整例子ο(=•ω<=)ρ⌒☆】 引入 首先我们来看一个例子,现在有两个字符串A和B,问你在A中是否有B,有几个?为了方便叙述,我们先给定两个字符串的值 A="abcaabababaa" B="abab" 那么普通的匹配是怎么操作的呢? 当然就是一位一位地比啦。(下面用蓝色表示已经匹配,黑色表示匹配失败) 但是我们发现这样匹配很 浪费! 为什么这么说呢,我们看到第4步: 在第4步的时候,我们发现第3位上c与a不匹配,然后第五步的时候我们把B串向后移一位,再从第一个开始匹配。 这里就有一个对已知信息很大的浪费,因为根据前面的匹配结果,我们知道B串的前两位是ab,所以不管怎么移,都是不能和b匹配的,所以应该直接跳过对A串第二位的匹配,对于A串的第三位也是同理。 或许这这个例子还不够经典,我们再举一个。 A="abbaabbbabaa" B="abbaaba" 在这个例子中,我们依然从第1位开始匹配,直到匹配失败: abbaab b babba abbaab a 我们发现第7位不匹配 那么我们若按照原来的方式继续匹配,则是把B串向后移一位,重新从第一个字符开始匹配 a b baabbbabba _ a