KMP算法(uva 1328)
来源:互联网 发布:全球购海淘宝 编辑:程序博客网 时间:2024/06/01 08:59
提问:假设存在一个长度为n的字符串T,模板是一个长度为m的字符串P,且m<=n。求出所有模板在字符串中的匹配点。
匹配点即为:满足T[i]=P[0],T[i+1]=P[1],.........,T[i+m-1]=P[m-1]的点i;
最简单的办法就是挨个找,如果有不对的,就换下一个匹配点。时间复杂度最大为O(m*(n-1)),不是很理想。
于是,我们就想到了能否根据模板自身的规律减少时间复杂度?KMP算法就诞生了!
KMP算法最关键的就是一个失配函数F(i),什么就做失配函数呢?
F(i)代表如果你在对比模板第i位时,失配了也就是不一样了,我们要跳到与模板的第 F(i)位比较,而不是直接重新开始比较。
给出一个建立失配函数的模板:
样例: 零 一 二 三 四 五 六 七 八 九 十 十一
下面是我的模板:
给道题加深对F(i)函数的理解: uva 1328
根据我们求F(i) 函数的方法,可以看出,如果f(i)>0 代表 i前面的 f(i)个字符与前i-1个字符一样。
如果能形成循环必有 K*(i-F(i))=i;(K为整数) 仔细想想,必然成立;
我的代码:
#include <cstdio>
const int maxn = 1000000+10;
using namespace std;
char s[maxn];
int f[maxn];
int main (){
int n,kase=0;
while (scanf("%d",&n)!=EOF&&n){
scanf("%s",s);
f[0]=f[1]=0;
for (int i=1;i<n;i++){
int j=f[i];
while (j&&s[i]!=s[j]) j=f[j];
f[i+1]=s[i]==s[j]?j+1:0;
}
printf("Test case #%d\n",++kase);
for (int i=2;i<=n;i++){
if (f[i]>0&&i%(i-f[i])==0) printf("%d %d\n",i,i/(i-f[i]));
}
printf("\n");
}
return 0;
匹配点即为:满足T[i]=P[0],T[i+1]=P[1],.........,T[i+m-1]=P[m-1]的点i;
最简单的办法就是挨个找,如果有不对的,就换下一个匹配点。时间复杂度最大为O(m*(n-1)),不是很理想。
于是,我们就想到了能否根据模板自身的规律减少时间复杂度?KMP算法就诞生了!
KMP算法最关键的就是一个失配函数F(i),什么就做失配函数呢?
F(i)代表如果你在对比模板第i位时,失配了也就是不一样了,我们要跳到与模板的第 F(i)位比较,而不是直接重新开始比较。
给出一个建立失配函数的模板:
void getFail (char *P,int *f){ //构建失配函数 f为失配函数 P为模板串 int m=strlen(P); f[0]=f[1]=0; for (int i=1;i<m;i++){ int j=f[i]; while (j&&P[i]!=P[j]) j=f[j]; f[i+1]=P[i]==P[j]?j+1:0; }}
样例: 零 一 二 三 四 五 六 七 八 九 十 十一
p[i] A B R A C A D A B R A
f[i] 0 0 0 0 1 0 1 0 1 2 3 4
在失配函数知道的基础上我们写搜索函数就很好写了:下面是我的模板:
int find(char *T,char *P,int *f) { //P为模板串 T为比较串 f为失配函数 int n=strlen(T); int m=strlen(P); getFail(P,f); int j=0; for (int i=0;i<n;i++){ while (j&&P[j]!=T[i]) j=f[j]; //按照失配函数调整比较的位置 if (P[j]==T[i]) j++; if (j==m) ans++; //找到子串 输出所在位置 } return 0;}
给道题加深对F(i)函数的理解: uva 1328
根据我们求F(i) 函数的方法,可以看出,如果f(i)>0 代表 i前面的 f(i)个字符与前i-1个字符一样。
如果能形成循环必有 K*(i-F(i))=i;(K为整数) 仔细想想,必然成立;
我的代码:
#include <cstdio>
const int maxn = 1000000+10;
using namespace std;
char s[maxn];
int f[maxn];
int main (){
int n,kase=0;
while (scanf("%d",&n)!=EOF&&n){
scanf("%s",s);
f[0]=f[1]=0;
for (int i=1;i<n;i++){
int j=f[i];
while (j&&s[i]!=s[j]) j=f[j];
f[i+1]=s[i]==s[j]?j+1:0;
}
printf("Test case #%d\n",++kase);
for (int i=2;i<=n;i++){
if (f[i]>0&&i%(i-f[i])==0) printf("%d %d\n",i,i/(i-f[i]));
}
printf("\n");
}
return 0;
}
为什么我这篇文章发的就这么费劲呢?T_T 深夜发,不管如何就是保存不成功。白天发也保存不成功,成功一次后发现,重复发了n回。又要重新删除。
0 0
- KMP算法(uva 1328)
- UVA 1328 KMP算法
- uva uva 1328 - Period ---KMP算法
- UVA 1351-String Compression(KMP算法+DP)
- uva 1328 Period(KMP循环节)
- uva 1328 Period(KMP)
- UVA 1328 - Period (KMP)
- UVA 1328 Period(KMP)
- uva 1328 - Period (周期串的判断 kmp)
- kmp算法(转载)
- KMP算法(转)
- (精)kmp算法
- (四)KMP算法
- KMP算法(1)
- KMP算法(2)
- KMP算法(站位)
- KMP算法(1)
- KMP算法(2)
- EL表达式简述
- Linux下Kill函数用法
- Sort Colors -- LeetCode
- 操作系统--处理器调度
- poj 1575 Easier Done Than Said?【字符串处理】
- KMP算法(uva 1328)
- 项目进阶 之 集群环境搭建(一)概述
- poj 3420 Quad Tiling(状态压缩矩阵递推)
- Subsets -- LeetCode
- Leetcode: Permutations 理解分析
- 黑马程序员_.NET字符串
- 黑马程序员 ----- Java基础 之 IO 基本规律总结 Day05
- Container With Most Water
- Regular Expression Matching