kmp算法

kmp

瘦欲@ 提交于 2019-11-28 08:11:29
kmp 针对 C 风格字符串的next数组公式 上图中使用的自定的串结构, 下标从1开始的 , 下方代码是使用C风格字符串, 下标从0开始的, 公式修改如下: KMP 算法代码实现 含有调试代码。 # include <stdio.h> # include <string.h> # include <stdlib.h> # define NDEBUG /*需要调试信息输出请注释此宏*/ /*获取next数组*/ void get_next ( const char * t , int * next ) { int i , j ; i = 0 ; j = - 1 ; /*调整j为-1,代表主串从失配位置下一个位置 在 和模式串重头开始匹配*/ next [ 0 ] = - 1 ; int t_len = strlen ( t ) ; while ( i < t_len ) { if ( - 1 == j || t [ i ] == t [ j ] ) { ++ i ; ++ j ; next [ i ] = j ; } else { j = next [ j ] ; } } } /*匹配, 在main串中匹配pattern*/ int subString ( const char * s , const char * t ) { int i = 0 ; /

KMP算法

[亡魂溺海] 提交于 2019-11-27 05:39:03
#include<bits/stdc++.h> using namespace std; char A[1007],B[1007]; int P[1007],n,m; void pre() { P[1]=0; int j=0; for(int i=1;i<m;i++) { while(j>0 && B[j+1]!=B[i+1]) j=P[j]; if(B[j+1]==B[i+1]) j++; P[i+1]=j; } } int kmp() { int ans=0,j=0; for(int i=0;i<n;i++) { while(j>0 && B[j+1]!=A[i+1]) j=P[j]; if(B[j+1]==A[i+1]) j++; if(j==m) { ans++; j=0;//手动移到子串头部,避免重复匹配 } } return ans; } int main() { while(scanf("%s%s",A+1,B+1)==2) { m=strlen(B+1); n=strlen(A+1); pre(); cout<<kmp()<<endl; } return 0; 来源: https://www.cnblogs.com/zhouzhihao/p/11347837.html

KMP算法实现

落花浮王杯 提交于 2019-11-26 18:31:29
算法这篇文章写得很明了: http://news.cnblogs.com/n/176771/ 以下是实现: KMP.cc #include <iostream> #include <cstring> #include <cstdlib> // Calc partition table void mkRpTab( const char * str, int * tab, int len) { for ( int i= 0 ; i<len; ++ i) { int j = i; for (; j> 0 ; -- j) { if (strncmp(str, str+i-j+ 1 , j) == 0 ) break ; } tab[i] = j; std::cout << tab[i] << " " ; } std::cout << std::endl; } // kmp void kmp() { const char * meterial = " BBC ABCDAB ABCDABCDABDE " ; const char * keyStr = " ABCDABD " ; std::cout << " meterial: " << meterial << std::endl; std::cout << " keyStr: " << keyStr << std::endl; int *

kmp算法模板

*爱你&永不变心* 提交于 2019-11-26 17:42:40
目的:在字符串T中查找字符串P的出现位置,预处理P字符串得到fail数组 时间复杂度:O(|P|+|T|) 自用模板: #include <iostream> #include <string.h> using namespace std; int Next[1110]; void get_Next(char *p) { int m=strlen(p); Next[0]=Next[1]=0; for(int i=1;i<m;i++) { int j=Next[i]; while(j&&p[i]!=p[j]) {j=Next[j];} Next[i+1]=p[i]==p[j]?j+1:0; } } int kmp(char *T,char *s) { int n=strlen(T),m=strlen(s); get_Next(s); int j=0; for(int i=0;i<n;i++) { while(j&&T[i]!=s[j]) {j=Next[j];} if(s[j]==T[i]) {j++;} if(j==m) { return i-m+1; } } return -1; } int main() { char s[1100],T[1100]; cin>>T>>s; cout<<kmp(T,s)<<endl; //在T中找s return 0; } View Code

kmp算法

人盡茶涼 提交于 2019-11-26 17:00:15
————————————————————时光点燃了少年的梦想....... 1. abcdef 的前缀:  a,   ab,   abc,   abcd,   abcde   (abcdef 可不是前缀哦!) abcdef 的后缀:  f,   ef,   def,   cdef,     bcdef,  (abcdef可不是后缀哦!) abcdef 的 前缀后缀最长公共元素长度 为  0         (因为其前缀与后缀没有相同的!) ababa的前缀:    a,  ab,  aba,  abab,   ababa的后缀:    a,  ba,  aba,  baba, ababa的 相同前缀后缀的最大长度 为:  3 ascesubluffy 的 prefix:      a,  as,  asc,  asce,  asces,  ascesu,  ascesub,  ascesubl,  ascesublu,  ascesubluf,  ascesubluff, asecesubluffy 的postfix:   y,  fy,   ffy,    uffy,  luffy,   bluffy,  ubluffy,   subluffy,   esubluffy,   cesubluffy,  scesubluffy, 长度为 len 的字符串的前缀与后缀的个数为 2*

HDOJ-3746(KMP+最小循环结)

有些话、适合烂在心里 提交于 2019-11-26 16:06:25
Cyclic Nacklace HDOJ-3746 本题还是使用KMP算法,需要使用到前缀数组 利用前缀数组计算最小循环节:即t=n-pi[n-1]. 最后输出还需要的珠子,当然还有判断什么时候输出为0. #include<iostream> #include<cstdio> #include<cstring> #include<string> using namespace std; string a; int pi[100010]; void Pi(string s){ memset(pi,0,sizeof(pi)); int n=s.length(); pi[0]=0; for(int i=1;i<n;i++){ int j=pi[i-1]; while(j>0&&s[i]!=s[j]){ j=pi[j-1]; } if(s[i]==s[j]) j++; pi[i]=j; } } int main(){ ios::sync_with_stdio(false); cin.tie(0); int t; cin>>t; while(t--){ cin>>a; Pi(a); int n=a.length(); int t=n-pi[n-1];//循环结 if(n%t==0&&(n/t>1)){ cout<<0<<endl; }else{ cout<<t-n%t<<endl; } }

HDOJ-1711(KMP算法)

ε祈祈猫儿з 提交于 2019-11-26 15:56:34
Number Sequence HDOJ-1711 1.这里使用的算法是KMP算法,pi数组就是前缀数组。 2.代码中使用到了一个技巧就是用c数组看成是复合字符串,里面加一个特殊整数位-1000006,因为它永远不会出现在数组中。 3.额外需要注意的就是,需要加快速输入输出语句,因为涉及到的数据量有点大,所以会超时,当然,也可以选用scanf也可以。 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int n,m; int a[1000006],b[10004]; int pi[1000006]; int c[1010010]; void Pi(int len){ memset(pi,0,sizeof(pi)); int n=len; pi[0]=0; for(int i=1;i<n;i++){ int j=pi[i-1]; while(j>0&&c[i]!=c[j]){ j=pi[j-1]; } if(c[i]==c[j]) j++; pi[i]=j; } } int main(){ ios::sync_with_stdio(false);//不加这两条语句会超时 cin.tie(0); int t; cin>>t; while(t--){

线性表-串:KMP模式匹配算法

妖精的绣舞 提交于 2019-11-26 14:59:22
一、简单模式匹配算法(略,逐字符比较即可) 二、KMP模式匹配算法 next数组:j为字符序号,从1开始。 (1)当j=1时,next=0; (2)当存在前缀=后缀情况,next=相同字符数+1; (3)当 前缀 != 后缀 且j != 1时,next=1。 如下: abcdex next=011111 abcabx next=011123 ababaaaba next=011234223 说明:0位置为情况1; 1、2位置为情况3; 3-5位置一直有前缀对称,所以一直累加; 6位置前缀不对称,j=next[ j ]找对称子串开始位置;如果没有继续j= next[ j ]直到 j = 0,next为0; 此处 i = 6, j = 4;第一次找: j = next[4] = 3, T[3] != T[6] ,没找到;第二次找: j= next[ 3 ] =1, T[2] == T[6], 找到累加 j+1 =2; 7位置同上; 8位置在7位置基础累加得到。 aaaaaaaab next=012345678 说明:0位置为情况1; 1位置为情况3; 2-8位置一直有前缀对称,所以一直累加。 代码如下: 1: void get_next( char T[], int * next) 2: { 3: int i = 1; 4: int j = 0; 5: 6: next[1] = 0;

KMP算法

扶醉桌前 提交于 2019-11-26 14:54:43
前提技能: 前缀数组 参考博客: KMP算法(kuangbin) const int maxn=1e5; int Next[maxn]; /*求前缀数组*/ /*t[0]对应Next[1]*/ /*Next[0]=-1*/ void getNext(string t) { int i=0,j=-1,n=t.length(); Next[0]=-1; while(i<n) { if(j==-1||t[i]==t[j]) Next[++i]=++j; else j=Next[j]; } } /*求 t 在 s 中出现的次数(可交叉)(即:s="bababa" t="baba" KMP_count()=2)*/ int KMP_count(string s,string t) { int ans=0,slen=s.length(),tlen=t.length(); if(slen==1&&tlen==1) { if(s==t) return 1; else return 0; } getNext(t); for(int i=0,j=0;i<slen;++i) { while(j>0&&s[i]!=t[j]) j=Next[j]; if(s[i]==t[j]) j++; if(j==tlen) ans++,j=Next[j]; } return ans; } /*求 t 在 s

KMP算法模板

浪子不回头ぞ 提交于 2019-11-26 12:17:05
KMP算法模板 原理 见参考文章 模板 #include <iostream> #include <cstring> #define max_n 100005 using namespace std; char s[max_n] = {'a','a','b','a','a','a','b','c'}; char p[max_n] = {'a','a','a','b'}; int nxt[max_n];//nxt跳转表,nxt[k]表示在k之前有的最大相同前后缀的长度 void get_next(char* p,int nxt[])//构造nxt表 { int pLen=strlen(p); nxt[0] = -1;//nxt表首元素必为-1,表示没元素会和他配对,要重新开始匹配模式串 int k = -1;//初始为-1,重新开始的标志也是-1 int j = 0; while(j<pLen-1) { //p[j]是后缀,p[k]是前缀 if(k=-1||p[j]==p[k])//如果重新匹配或者成功匹配 { ++j; ++k; if(p[j]!=p[k]) { nxt[j] = k; } else nxt[j] = nxt[k];//避免p[j]==p[nxt[j]],所以继续递归,k=nxt[k]=nxt[nxt[k]] } else { k = nxt[k]; } } }