kmp

KMP模板

蹲街弑〆低调 提交于 2019-11-26 22:27:05
第二次理解了,一个讲的可以的博客: https://blog.csdn.net/starstar1992/article/details/54913261#commentBox #include<bits/stdc++.h> using namespace std; char s1[1000001],s2[1000001]; int next[1000001]; void Next(int len2) { next[0]=-1; int k=-1; for(int i=1;i<len2;i++) { while(k>-1&&s2[i]!=s2[k+1]) k=next[k]; if(s2[i]==s2[k+1])k++; next[i]=k; } } //abavababababc //abababc //-1-1 0 1 2 1 -1 void kmp(int len1,int len2) { for(int i=0,j=-1;i<len1;i++)///是s2的下标-1 { while(s1[i]!=s2[j+1]&&j>-1) j=next[j]; if(s1[i]==s2[j+1])j++; if(j==len2-1) { cout<<i-j+1<<endl; j=next[j]; } } } int main() { int i; scanf("%s%s",s1,s2)

Censoring(栈+KMP)

会有一股神秘感。 提交于 2019-11-26 21:14:47
【KMP】Censoring 题目描述 Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so they have plenty of material to read while waiting around in the barn during milking sessions. Unfortunately, the latest issue contains a rather inappropriate article on how to cook the perfect steak, which FJ would rather his cows not see (clearly, the magazine is in need of better editorial oversight). FJ has taken all of the text from the magazine to create the string S of length at most 10^6 characters. From this, he would like to remove occurrences of a substring T to censor the

【KMP】OKR-Periods of Words

£可爱£侵袭症+ 提交于 2019-11-26 21:14:24
【KMP】OKR-Periods of Words 题目描述 串是有限个小写字符的序列,特别的,一个空序列也可以是一个串。一个串P是串A的前缀,当且仅当存在串B,使得A=PB。如果P≠A并且P不是一个空串,那么我们说P是A的一个proper前缀。 定义Q是A的周期,当且仅当Q是A的一个proper前缀并且A是QQ的前缀(不一定要是proper前缀)。比如串abab和ababab都是串abababa的周期。串A的最大周期就是它最长的一个周期或者是一个空串(当A没有周期的时候),比如说,ababab的最大周期是abab。串abc的最大周期是空串。 给出一个串,求出它所有前缀的最大周期长度之和。 输入 第一行一个整数k,表示串的长度。 接下来一行表示给出的串。 输出 输出一个整数表示它所有前缀的最大周期长度之和。 样例输入 8 babababa 样例输出 24 提示 对于全部数据,1<k<1e6 【题意】: 看题意,人话吗?我真的看了很久很久,最后还是找博客上的解释才看懂是什么 意思。。。 参考博客: 蒟蒻のblog 思路 先把题面转成人话: 对于给定串的每个前缀i,求最长的,使这个字符串重复两边能覆盖原前缀i的前缀(就是前缀i的一个前缀),求所有的这些“前缀的前缀”的长度和 利用nextnext的性质:前缀ii的长度为next[i]的前缀和后缀是相等的 这说明

【kmp】剪花布条

一世执手 提交于 2019-11-26 21:10:35
问题 K: 【KMP】剪花布条 题目描述 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案。对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢? 输入 输入中含有一些数据,分别是成对出现的花布条和小饰条,其布条都是用可见ASCII字符表示的,可见的ASCII字符有多少个,布条的花纹也有多少种花样。花纹条和小饰条不会超过1000个字符长。如果遇见#字符,则不再进行工作。 输出 输出能从花纹布中剪出的最多小饰条个数,如果一块都没有,那就老老实实输出0,每个结果之间应换行。 样例输入 abcde a3 aaaaaa aa # 样例输出 0 3 【题解】 裸的kmp题目。。。 1、对于匹配串进行get_Next() 2、对于文本串用匹配串Next数组快速匹配,注意加入匹配后的操作语句。 【代码】: 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 1e3+10; 4 char s[N],p[N]; 5 int Next[N],n,m,ans; 6 void get_Next(){ 7 Next[0] = 0 ; 8 for(int i=2,j=0 ; i<=m ;i++){ 9 while( j && p[i] != p[j+1] ) j = Next[j] ; 10

KMP复习

让人想犯罪 __ 提交于 2019-11-26 21:02:10
KMP复习 kmp真的是一个好算法,将暴力 \(O(nm)\) 的匹配改进成了 \(O(n+m)\) 。 nb! 推荐一个 视频 。 #include<bits/stdc++.h> using std::cin; using std::cout; using std::endl; using std::string; const int maxn = 1000005; string s1, s2; int next[maxn]; int main() { std::ios::sync_with_stdio(false); cin >> s1 >> s2; next[0] = 0; for(int i = 1, j = 0; i < s2.size(); i++) { while(j > 0 && s2[j] != s2[i]) j = next[j - 1]; if(s2[j] == s2[i]) j++; next[i] = j; } for(int i = 0, j = 0; i < s1.size(); i++) { while(j > 0 && s2[j] != s1[i]) j = next[j - 1]; if(s2[j] == s1[i]) j++; if(j == s2.size()) { cout << i - j + 2 << endl; } } for(int

POJ 3461 Oulipo

二次信任 提交于 2019-11-26 20:07:48
之前比赛的时候,一道KMP的题目没有做出来,很是郁闷。最近一两天仔细研究了一下KMP,收获不少。 基本的KMP思想算法什么的就不再赘述了。只是我在网上找资料的时候发现KMP的失配数组(next[])有两个版本,但是几乎没有资料将这两个版本的next[]做一个较好的分析。于是,写了这篇blog,对这两类next[]做了一个简单的分析,希望对大家有帮助,也希望大家能指出其中的错误和不足。由于直接贴文本格式难以控制,于是一部分内容被做成了图片。分析如下: 第一类next数组求解函数: Code 1 void KMP_next( char b[], int pre[]) { 2 int n = ( int )strlen(b), k; 3 pre[ 0 ] = - 1 ; k = - 1 ; 4 for ( int i = 1 ; i < n; i ++ ) { // 没有i == n 5 while (k > - 1 && b[k + 1 ] != b[i]) k = pre[k]; 6 if (b[k + 1 ] == b[i]) k ++ ; 7 pre[i] = k; 8 } 9 } 第二类next数组求解函数: Code 1 void KMP_next( char s[], int pre[]) { 2 int i = 0 , j = - 1 , n = ( int

kmp算法散记

邮差的信 提交于 2019-11-26 19:58:23
1. https://blog.csdn.net/abcjennifer/article/details/5794547 #include<bits/stdc++.h> using namespace std; char t[1000001],p[10001]; //文本串t,模式串p int next[10001]; //记录当前索引位置的前一个字符的相同前缀后缀的最长长度。 void getnext()//打表离线计算模式串p { int len=strlen(p); } int KMP(char t[],char p[]) //统计模式串p在文本串s出现次数(允许重叠) //文本串t,模式串p { int ans=0; //统计值 int i; //在文本串s上移动进位的索引“指针” int n=strlen(t);//文本串t的长度 int m=strlen(p);//模式串p的长度 if(n==1 && m==1) { if(t[0]==p[0]) return 1; else return 0; } getnext(p); //获得模式串p的next数组 int q=0; //在模式串q上移动进位的索引“指针” for(i=0;i<n;i++) { while(q>0 && p[q]!=t[i]) q=next[q]; if(p[q]==t[i]) q++; /

KMP:n+1次探

拜拜、爱过 提交于 2019-11-26 19:46:55
如你所见,这是我不知道第几次学KMP了。 推荐B站上电子科大的字符串专题。 引入:KMP是干什么的 KMP解决的是模式串P在源串T中出现次数的问题,比如模式串P为aba,源串为abababa,我们可以求出计算重叠的出现次数3,还可以求出不计算重叠的出现次数2。 next数组 [x] 最好不要用next命名next数组,某些OJ会报错 前(后)缀和真前(后)缀:字符串s前i个(i<=strlen(s))字符为其前缀,i!=strlen(s)时为真前缀,后缀和真后缀同理。 next[i]表示模式串P以i为尾的这个前缀,最长的公共真前缀和真后缀长度,例如abcabc,next[1:6]={0,0,0,1,2,3} 求next数组 假设我们已经知道next[1:i-1],求next[i]。 设last=next[i-1],则p[1:last]等于p[i-last:i-1],即模式串长度为i-1的前缀,前last个与后last个相同,且last最大,那么我们只需要检测p[i]与p[last+1]是否相等,相等就是last+1,否则要在这last个(p[i-last:i-1],即p[1:last])里面找,更新last=next[last],继续检测p[i]与p[last+1]是否相等,如此循环直到last=0,p[i]=p[1],即为1,否则为0。 那么只需要设置next[1]=0

扩展KMP(讲解+模版+例题)

白昼怎懂夜的黑 提交于 2019-11-26 19:45:50
在阅读这篇文章之前,我们假定你已经掌握了 KMP:n+1次探 里的定义。 引入:扩展KMP是干什么的 扩展KMP解决的是源串S的每一个后缀与模式串P的最长公共前缀的长度的问题,并求解出答案extend数组,例如,ababac与aba的extend数组是3 0 3 0 1 0,这里extend[i]表示s[i:5](i从0开始)与p[0:2]的最长公共前缀的长度。 next数组的定义 这里的next数组与KMP里的不同。 next[i]表示从i开始的p的后缀与p的最长公共前缀的长度,也就是,p对p求扩展KMP,可以参见 2019 Multi-University Training Contest 5 - 1006 - string matching 。 我们先假设已经有了next数组,来求extend,因为next数组的求法是和extend一样的。 扩展KMP 递推:已知extend[i-1],如何求extend[i]? 我们假设在前面匹配时,向右匹配到的最远坐标为last,是从first开始匹配的,也就是说s[first:last]=p[0:last-first]。可以推出s[i:last]=p[i-first:last-first],但这个不是和p的开头匹配,还不能用,我们取extend[i]=min(last-i+1, next[i-first]),看看p[i-first

扩展kmp模板

自古美人都是妖i 提交于 2019-11-26 18:04:53
目的:找出字符串S的所有后缀与字符串T的最长公共前缀,预处理Next[i]。    S字符串长度为n,T字符串长度为m。    Next[i],i∈[0,m),表示T的后缀i与T的最长公共前缀。    extend[i],i∈[0,n),表示T与S[i,n)的最长公共前缀。如果有一个extend[i]=m,则T在S中在i位置出现。 时间复杂度:O(|S|+|T|) 自用模板: #include <iostream> #include <string.h> using namespace std; const int maxn=1100; int Next[maxn],extend[maxn]; void get_Next(char *s) { int n=strlen(s); int i,j,k; for(j=0;1+j<n&&s[j]==s[1+j];j++); Next[1]=j; k=1; for(i=2;i<n;i++) { int len=k+Next[k],L=Next[i-k]; if(L<len-i) { Next[i]=L; } else { for(j=max(0,len-i);i+j<n&&s[j]==s[i+j];j++); Next[i]=j; k=i; } } Next[0]=n; } void ex_kmp(char *T,char *s) { int