ACM随笔 17.9.3 KMP
2017-09-03 20:15
162 查看
今天晚上才看见群里公告,= =线段树没有看,不过这两天看了一下KMP算法,主要用来处理字符串的子串问题。
假设有字符串s1和字符串s2,长度分别为n和m。在求解s2是否为s1的子串这个问题中,称s1为匹配串,s2为模式串。KMP算法是一个复杂度为O(n+m)的算法,既可以求出字符串s2是不是字符串s1的子串,又可以求出字符串s2在字符串s1中出现了多少次,每一次出现在什么位置。
KMP算法首先用O(m)的复杂度求出一个next数组,记录了关于字符串s2的信息,然后用O(n)的复杂度快速求出字符串s2在字符串s1中的位置。
若next[j]==k,则k为满足以下条件的最大值;s2[0...k-1]与s2[j-k...j-1]相同,且s2[k]与s2[j]不同。若不存在这样的k,则next[k]=-1;
![](https://img-blog.csdn.net/20170903200147606?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzc4MTcxOTQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
假设s1为匹配串,s2位模式串 ,next数组位失配指针。并且next已得到
i=j=0;
while(s1[i]!='\0'){
if(j!=-1&&s2[j]=='\0'){
j=0;
}
else{
while(j!=-1&&s1[i]!=s2[j])
j=next[j];
i++;
j++;
}
}
//最后还要检查s2[j]=='\0',满足条件,则s1[i-m...i-1]等同于s2[0...m-1];
循环的每一步都判断s1[i-j...i]与s2[0...j]是否相等。
如果相等则应该寻找s1[i-j]开头最多能匹配到多少,即令i和j都加1;
如果不相等,应该将s2右移,next数组已经标记s2右移多少能保持s1[i-j...i]与s2[0...j]仍相等。
一直进行下去,当s2[j]=='\0‘时,就表示匹配成功了一个串。
下面来说一下next的求法。
void cal_next(char *str, int *next, int len)
{
next[0] = -1;//next[0]初始化为-1,-1表示不存在相同的最大前缀和最大后缀
int k = -1;//k初始化为-1
for (int q = 1; q <= len-1; q++)
{
while (k > -1 && str[k + 1] != str[q])//如果下一个不同,那么k就变成next[k],注意next[k]是小于k的,无论k取任何值。
{
k = next[k];//往前回溯
}
if (str[k + 1] == str[q])//如果相同,k++
{
k = k + 1;
}
next[q] = k;//这个是把算的k的值(就是相同的最大前缀和最大后缀长)赋给next[q]
}
}
假设有字符串s1和字符串s2,长度分别为n和m。在求解s2是否为s1的子串这个问题中,称s1为匹配串,s2为模式串。KMP算法是一个复杂度为O(n+m)的算法,既可以求出字符串s2是不是字符串s1的子串,又可以求出字符串s2在字符串s1中出现了多少次,每一次出现在什么位置。
KMP算法首先用O(m)的复杂度求出一个next数组,记录了关于字符串s2的信息,然后用O(n)的复杂度快速求出字符串s2在字符串s1中的位置。
若next[j]==k,则k为满足以下条件的最大值;s2[0...k-1]与s2[j-k...j-1]相同,且s2[k]与s2[j]不同。若不存在这样的k,则next[k]=-1;
假设s1为匹配串,s2位模式串 ,next数组位失配指针。并且next已得到
i=j=0;
while(s1[i]!='\0'){
if(j!=-1&&s2[j]=='\0'){
j=0;
}
else{
while(j!=-1&&s1[i]!=s2[j])
j=next[j];
i++;
j++;
}
}
//最后还要检查s2[j]=='\0',满足条件,则s1[i-m...i-1]等同于s2[0...m-1];
循环的每一步都判断s1[i-j...i]与s2[0...j]是否相等。
如果相等则应该寻找s1[i-j]开头最多能匹配到多少,即令i和j都加1;
如果不相等,应该将s2右移,next数组已经标记s2右移多少能保持s1[i-j...i]与s2[0...j]仍相等。
一直进行下去,当s2[j]=='\0‘时,就表示匹配成功了一个串。
下面来说一下next的求法。
void cal_next(char *str, int *next, int len)
{
next[0] = -1;//next[0]初始化为-1,-1表示不存在相同的最大前缀和最大后缀
int k = -1;//k初始化为-1
for (int q = 1; q <= len-1; q++)
{
while (k > -1 && str[k + 1] != str[q])//如果下一个不同,那么k就变成next[k],注意next[k]是小于k的,无论k取任何值。
{
k = next[k];//往前回溯
}
if (str[k + 1] == str[q])//如果相同,k++
{
k = k + 1;
}
next[q] = k;//这个是把算的k的值(就是相同的最大前缀和最大后缀长)赋给next[q]
}
}
相关文章推荐
- <sdut-ACM>数据结构实验之串三:KMP应用
- ACM常用模板——扩展KMP
- 邝斌的ACM模板(扩展 KMP)
- 2017 ICPC-ACM全国邀请赛(陕西) 随笔
- KMP模式匹配算法-----ACM程序设计…
- ACM随笔------计蒜客 求平方根
- ACM_心情随笔
- ACM常用模板——字符串匹配——KMP
- 杭电acm 2594Simpsons’ Hidden Talents(kmp)
- acm专题---KMP模板
- ACM -- 算法小结(四)KMP(POJ3461)
- acm-icpc大连站随笔
- HDU 5510 Bazinga(KMP)——2015ACM/ICPC亚洲区沈阳站
- [HDU 5510][2015ACM/ICPC 亚洲区沈阳站] Bazinga KMP+剪支
- ACM题解转移计划--随笔记录
- 2017西安交大ACM小学期 神器插座 KMP匹配
- 2017 ACM-ICPC乌鲁木齐网络赛 G. Query on a string 【KMP+树状数组】
- 随笔一则(记ACM新秀赛)
- dutacm.club_1087_Common Substrings_(KMP)_(结合此题通俗理解kmp的next数组)
- 2017北京师范大学ACM校赛 J Just A String (KMP)