kmp总结及其应用
2013-04-28 20:41
183 查看
kmp含义
克努斯-莫里斯-普拉特算法,一种字符串查找算法。
字符串算法主要是用于主串 S( s1,s2,s3,...,sn ), 模式串T( t1,t2,...,tm ), 之间的匹配问题.
相对与模式匹配O(n^2)而言: 当 Si != Tj 失配时, 主串下标i不回溯, 而是将模式串下标j回溯到合适的地方,再继续比较 Tj ,Si.
时间复杂度极端情况是 O(N*M), 但是一般情况下总能保证O(N+M).
假定串 S( i-j+1, i ) 与 模式串 T( 1, j ) 匹配时, Si != Tj 不匹配,此时需j最短回溯到 k,
则存在 T(1,k-1) = T( j-k+1, j-1 ), 此时 k = next[j], 再令 Si 与 Tk 比较.
则我们得出 next[] 的定义:
next[i] = 0, 当 i = 0
next[i] = Max{ k | 1 < k < j, 且 T(1,k-1) = T(j-k+1,j-1),当此集合不空时 }
next[i] = 1, 其它情况.
next数组
next函数,表示对于模式串而言,其最长的前缀与后缀相同的长度.
有定义知道 next[1] = 0;
设 next[j] = k, 这表明在模式串中存在下列关系
T( 1, k-1 ) = T( j-k+1, j-1 )
此时 next[ j+1 ]的取值有两种情况:
1. 当 T[k] == T[j] 时, 此时有 T( 1,k ) = T( j-k+1, j ), 则此时 next[ j+1 ] = next[j] + 1
2. 但 T[k] == T[j] 时, 此时可把求 next函数值的问题看作是一个模式匹配的问题.整个模式串既是主串又是模式串.
按照前面主串与模式串匹配的思路, 则当 T[k] != T[j] 时, 应将模式串下标 k滑动到 next[k]时, 再与 T[j] 比较,
最终可能出现两种情况:
1. 匹配到, 此时 next[ j+1 ] = next[ k` ] + 1;
2. 一直无法匹配则最后会得到, next[ j+1 ] = 1.
应用模型
1. 模式串是否在主串中出现.
poj 3080 Blue Jeans
枚举其中一个串的主串,然后与其他串进行KMP匹配即可. 此题细节处理使用了STL.string.substr( 起点l, 数量num ).
View Code
克努斯-莫里斯-普拉特算法,一种字符串查找算法。
字符串算法主要是用于主串 S( s1,s2,s3,...,sn ), 模式串T( t1,t2,...,tm ), 之间的匹配问题.
相对与模式匹配O(n^2)而言: 当 Si != Tj 失配时, 主串下标i不回溯, 而是将模式串下标j回溯到合适的地方,再继续比较 Tj ,Si.
时间复杂度极端情况是 O(N*M), 但是一般情况下总能保证O(N+M).
假定串 S( i-j+1, i ) 与 模式串 T( 1, j ) 匹配时, Si != Tj 不匹配,此时需j最短回溯到 k,
则存在 T(1,k-1) = T( j-k+1, j-1 ), 此时 k = next[j], 再令 Si 与 Tk 比较.
则我们得出 next[] 的定义:
next[i] = 0, 当 i = 0
next[i] = Max{ k | 1 < k < j, 且 T(1,k-1) = T(j-k+1,j-1),当此集合不空时 }
next[i] = 1, 其它情况.
int kmp( char *S, char *T ){ // 主串S,模式串T, 下标皆从1开始. int la = strlen(S), lb = strlen(T); int i = 1, j = 1; while( i <= la && j <= lb ){ if( j == 0 || S[i] == T[j] ) i++, j++; else j = next[j]; //模式串向前滑动到 nxt[j]位置,继续比较 } if( j > lb ) return i-j; //匹配成功,返回最初匹配点 return -1; //匹配失败 }
next数组
next函数,表示对于模式串而言,其最长的前缀与后缀相同的长度.
有定义知道 next[1] = 0;
设 next[j] = k, 这表明在模式串中存在下列关系
T( 1, k-1 ) = T( j-k+1, j-1 )
此时 next[ j+1 ]的取值有两种情况:
1. 当 T[k] == T[j] 时, 此时有 T( 1,k ) = T( j-k+1, j ), 则此时 next[ j+1 ] = next[j] + 1
2. 但 T[k] == T[j] 时, 此时可把求 next函数值的问题看作是一个模式匹配的问题.整个模式串既是主串又是模式串.
按照前面主串与模式串匹配的思路, 则当 T[k] != T[j] 时, 应将模式串下标 k滑动到 next[k]时, 再与 T[j] 比较,
最终可能出现两种情况:
1. 匹配到, 此时 next[ j+1 ] = next[ k` ] + 1;
2. 一直无法匹配则最后会得到, next[ j+1 ] = 1.
void GetNext( char *T, int *nxt ){ int len = strlen(T); int i = 0, j = 1; nxt[1] = 0; while( j <= len ){ if( i == 0 || T[i] == T[j] ) nxt[ ++j ] = ++i; else i = nxt[i]; } }
应用模型
1. 模式串是否在主串中出现.
poj 3080 Blue Jeans
枚举其中一个串的主串,然后与其他串进行KMP匹配即可. 此题细节处理使用了STL.string.substr( 起点l, 数量num ).
View Code
#include<cstdio> #include<cstring> #include<cstdlib> const int N = 400010; char s ; int res , nxt ; int main(){ while( scanf("%s", s) != EOF){ int len = strlen(s); int i = 0, j = 1; nxt[1] = 0; while( j <= len ){ if( i == 0 || s[i-1] == s[j-1] ) nxt[++j] = ++i; else i = nxt[i]; } int cnt = 0, x = nxt[len+1]; res[cnt++] = len; while( x > 1 ) { res[cnt++] = x-1; x = nxt[x]; } for(int i = cnt-1; i >= 0; i--) printf( i == 0 ? "%d" : "%d ", res[i] ); puts(""); } return 0; }
相关文章推荐
- kmp总结及其应用
- 【串和序列处理 5】总结---自动机,KMP算法,Extend-KMP,后缀树,后缀数组,trie树,trie图及其应用
- 【cocos2d-x 2.x 学习与应用总结】10: cocos2d-x自带的shader及其使用
- C++技术问题总结-第14篇 常用设计模式及其应用场景
- 有关Activity样式 、状态栏透明、屏幕亮度问题应用场景及其总结
- 总结2: PHP中的魔术方法及其应用场景
- 常见数组&字符串API及其应用场景总结
- (转载总结)SVD 及其在推荐系统中的应用
- 数据结构笔记--总结各种排序算法及其应用
- Quartz调度框架应用总结<2>--作业及其相关
- UML基础及其应用视频总结
- 【算法】排序算法及其应用总结
- 数据库系统原理及其应用总结---ShinePans
- 数据结构笔记--总结各种查找算法及其应用
- 强连通分支及其应用(2-SAT)总结
- 安卓中 广播 服务 及其简单应用范围的一些总结
- JavaScript知识总结—cookie及其应用
- Java反射及其在Android中的应用学习总结
- 卡特兰数定义及其几个常用的应用(附例子"括号匹配"代码)+应用总结
- Java中的String、StringBuffer和Math类--学习java语言及其网络应用总结