比起ac自动机,kmp就一个next数组,理解了如何初始化next后就可以搞一些模板题了,下面是还不错的学习资料,清晰易懂,自己用的模板也来自它:

 http://chaoswork.com/blog/2011/06/14/kmp%E7%AE%97%E6%B3%95%E5%B0%8F%E7%BB%93/

kmp模板

next[0]=-1;j=-1;
for(i=0;i<m;)
{while(j>=0 && p[i]!=p[j])j=next[j];i++;j++;next[i]=j;
}for(i=0,flag=0,j=0;i<n;)
{while(j>=0 && p[j]!=t[i])j=next[j];i++;j++;//已经匹配了模式串的多少个if(j==m)//匹配成功
}

接下来需要更加深入地了解next数组,许多题目需要用到它的定义来预处理字符串:

xdu 1154

显然,用2次kmp处理处前缀和后缀在各点的匹配情况,用dp记录符合要求的子串,有几个要注意的地方:(调了2个小时T_T)

1.前缀的其实位置不但要在后缀的前面,终止位置不能超过后缀的终止位置,也就是说前缀不能包含后缀.

2. 

View Code

for(i=0,flag=0,j=0;i<n;)
{while(j>=0 && p[j]!=t[i])j=next[j];i++;j++;
  if(j==m)//若在此处记录则会出现bug,因为此时匹配完成点是i-1
}

CF也有一道与上面类似的题,需要用kmp预处理最左端前缀和最右端后缀

http://codeforces.com/contest/149/problem/E

循环节问题

它还能用来求周期字符串的循环节HDU1358:

性质:

当且仅当len%(len-next[len])==0时,str[next[len]~len-1]为最小循环节

要证明它需要说明3点:

1.一个字符串str是周期串,假设s1为它的循环节,则str=s1 s1...s1(n个)

推导出=>len%(len-next[len])==0成立.

2.next[len]~len-1为s1 ,len%(len-next[len])==0时

推导出=>str为周期串,s1为最小循环节

3.如何保证是最小的.

证明:

1.由next的性质知道,s[1~next[len]-1]与s[1~len-1]有最长的相等的前缀和后缀s,很显然s就是n-1个s1了.

2.设s1的长度为L,由于len%L==0 , str可以分解成若干个长度为L的小串,设它们从左到右依次为

a, a... an

根据匹配关系得

a1=a2;

a2=a3;

..

an-1=an;

因此a1=a2=a3...=an;

3.next[len]保证了前缀与后缀最大化,如果循环节s1存在而s1内还有循环节s1',则next[len]可以向后移动,与定义矛盾.

相等的循环同构问题

hdu3374 string problem

分析:

  最大和最小的循环同构字符串可以分开处理,求位置可以利用最小最大表示法(03wc论文 周源)

  求出现的次数可以用kmp扫一遍,但利用 循环节 可以更快地得到答案.

性质:

  字符串str由k个最小循环节s1组成,则它的相等循环同构数为k.

证明:

  设相等循环同构数为p,我们可以利用循环节s1构造出k个相等的循环同构,于是p>=k;

  下面证明p<=k:

    如果p>k

    假设在移动完s1到尾部前,出现了相同的循环同构串,不妨设此时移动的串为s2,

    则利用 循环节性质2第1种情况的推理方法 可以知道s2为字符串的一个循环节

    且s2的长度<s1,与s1为最小循环节的条件矛盾,因此p<=k.

  于是p只能等于k.

拓展KMP

  有很长一段时间单纯地以为拓展kmp只是kmp倒过来跑,后来发现很多问题其实无法转换成kmp解决,于是怒学了一下拓展kmp.

  首先比较一下kmp和拓展kmp解决的问题:

  kmp解决了求所有主串的前缀pre[i] (0<=i<n)的后缀与模式串前缀的最大匹配长度问题;

  拓展kmp解决了所有主串的后缀suf[i]前缀,与模式串前缀的最大匹配长度问题.

  

 1 void getNext() {
 2     int l = 1, r = -1, i, j;
 3
 4     for (next[0] = 0, i = 1; p[i]; ++i) {
 5         if (i + next[i - l] - 1 < r) next[i] = next[i - l];
 6         else {
 7             for (j = max(r - i + 1, 0); p[i + j] && p[i + j] == p[j]; ++j);
 8             next[i] = j; l = i; r = i + j - 1;
 9         }
10     }
11     next[0] = i;
12 }

  设模式串为str;

  定义next[i]为 str 与 它的后缀suf[i]的最大公共前缀长度.

  r是当前已经确定匹配区间的最右端点,l是对应的左端点,即 r=l+next[l]-1;

  当要求next[i]时

  根据 next定义 str[ l , l+next[l]-1 ] == str[ 0 , next[l]-1 ];

  得到 str[ i , l+next[l]-1 ] == str[ i-l , next[l]-1 ];

  设s1=str[ i , l+next[l]-1 ];

  讨论以下情况:

  1. 若  i在 [l,r] 区间内

   next[i-l]的值我们已经知道,这时候需要讨论:

    如果  next[i-l] 小于 s1 的长度,那么可以知道在下标为 next[i-l] 的位置必定会失配,于是next[i]=next[i-l];

    如果  next[i-l] 大于或等于 s1 的长度,那么直到r位置,我们都可以确定已经匹配上了,接下来需要确定r后面

    位置的匹配情况,而此时i已经匹配了r-i+1的长度,next[i]从这个值开始计数就可以了,计数完成后i+next[i]-1

    已经大于r,因此要更新   r=i+next[i]-1 , l=i ;

  2.若 i不在[l,r]的区间内,即 i > r, 前面得到的信息无法用到,于是我们需要从头将str[i]与str[0]进行匹配,当然也要记得更新l,r.

   复杂度:

    2个循环变量i,j都是单调增的,而他们最多增加n次,因此 复杂度是线性的.

  拓展kmp求循环节的方法参考kmp求循环节部分.

  知道这些后可以来解决这个问题

【总结】字符串匹配: KMP 和 拓展KMP相关推荐

  1. 字符串匹配—BF算法和KMP算法

    BF算法 本章重点是是KMP算法,但是由于其较难理解,先从更简单朴素的BF算法开始. 其思路非常简单 也就是,对这样两个字符串(称短的为模式串,长的为主串): 让主串和模式串的每个字符逐个匹配,如果从 ...

  2. 字符串匹配(一)—— KMP / MP

    目的:判断目标串(T串)中是否含有模式串(P串). 失配 T t0 t1 t2 -- tk tk+1 P p0 p1 p2 -- pk 由于字符串T和P第一个不相等的字符出现在位置k,所以两字符前k个 ...

  3. 字符串匹配BF/RK/BM/KMP算法

    主串长度m,匹配串(模式串)长度n. 一.BF 强制算法比较,最容易想到的,时间复杂度O(m*n) 二.RK 计算出匹配串的哈希值,遍历主串,求每次对应位置相同长度的子串哈希值,比较两者是否相同. 若 ...

  4. 字符串匹配代码C语言,KMP算法(快速模式匹配算法)详解以及C语言实现

    通过上一节的介绍,学习了普通模式匹配算法,大体思路是:模式串从主串的第一个字符开始匹配,每匹配失败,主串中记录匹配进度的指针 i 都要进行 i-j+1 的回退操作(这个过程称为"指针回溯&q ...

  5. KMP字符串匹配 洛古3375 kmp水题

    题目大意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next 分析 好久没动到博客,因为中考. 但是中考结 ...

  6. 字符串匹配KMP算法

    字符串匹配KMP KMP过程其实就是去找下一个更好的状态的过程,省略去了中间穷举的无用过程,直接跳到下一个更好的状态,通过模式串本身的信息,站在模式串的角度来考虑问题 取长的一对 若想让模式串直接从S ...

  7. 三十五、字符串匹配问题--KMP算法

    一.暴力匹配算法实现字符串匹配 如果用暴力匹配的思路,并假设现在 str1 匹配到 i 位置,子串 str2 匹配到 j 位置,则有: 如果当前字符匹配成功(即 str1[i] == str2[j]) ...

  8. 字符串匹配的KMP算法和C语言代码,不需要思考就能理解

    KMP算法用于判断一个字符串是否包含另一个字符串,如果包含就返回脚标.其实KMP算法本身特别简单,我看了几篇本章都号称简单易懂,结果看得我云里雾里,直到我看到了阮一峰:字符串匹配的KMP算法,才真正看 ...

  9. 字符串匹配のKMP【专题@AbandonZHANG】

    算法详解 很长时间内都没有能够很理解KMP算法的精髓,尤其是很多书上包括<算法导论>没有把next函数(亦或 π函数)讲解的很透彻. 今天去看了matrix67大牛博客中关于kmp部分的讲 ...

最新文章

  1. Django博客系统(推荐文章数据展示)
  2. 备份mysql数据库攻略_mysql备份实例攻略
  3. Third Week :Linux下的C语言
  4. Java 中的 Switch 都支持 String 了,为什么不支持 long?
  5. Unchecked call to ‘mapoPair(PairFunction<T,K2,V2>)‘ as a member of raw type
  6. python summary结果提取_Python coverage.summary方法代码示例
  7. 2010 北大软件及微电子学院 《软件实现技术》小组博客
  8. 安全筛选器创建与管理
  9. 遍历字典时用与不用iter的区别
  10. c语言 char *b,C语言:char*a,*b; *b*=a是什么意思? 如图所示
  11. matlab p q的确定,基于MATLAB软件的P-Q分解法潮流计算 (1)
  12. 几句话就能让你明白:热备份路由选择协议(HSRP)
  13. 求解线性方程的数值方法——Matlab中实现算法
  14. 浅谈A*算法如何演变为rrt算法
  15. 群晖经典第三方套件_强烈推荐群晖下载套件玩物下志
  16. 武汉理工大学计算机学院转专业细则,计算机学院武汉理工大学2009年各学院转专业工作实施细则.doc...
  17. TDP158RSBR 6-Gbps 转接驱动器,兼容HDMI2.0
  18. 阈值处理(Threshold processing)
  19. 人脑能用计算机算法吗,电脑到人脑,计算机必不可少的4大思维
  20. 手机黑屏,但是按开机键有震动,能进系统,usb也能识别fastboot和rec(bl已解)

热门文章

  1. 现代软件工程 结对编程 (II) 电梯调度 算法和测试框架
  2. 创新, FMA SMA 世界第一台VCD机的故事
  3. java五子棋实训训心得,java五子棋实习报告
  4. 二十年后我发明了保姆机器人作文_机器人保姆我的发明作文450字
  5. oracle 时间间隔,ORACLE JOB间隔时间参考
  6. jdk中java_怎样使用JavaJDK中Java?
  7. python画五角星填充不同颜色_不同颜色牡丹怎么画?3种牡丹图解教你画,适合0基础学习,收藏...
  8. php中arraymultisort,php 数组函数array_multisort()用法
  9. rocketmq 消息指定_进大厂必备的RocketMQ你会吗?
  10. c语言输出后面空格,新人提问:如何将输出时每行最后一个空格删除