POJ 3461 Oulipo

之前比赛的时候,一道KMP的题目没有做出来,很是郁闷。最近一两天仔细研究了一下KMP,收获不少。

基本的KMP思想算法什么的就不再赘述了。只是我在网上找资料的时候发现KMP的失配数组(next[])有两个版本,但是几乎没有资料将这两个版本的next[]做一个较好的分析。于是,写了这篇blog,对这两类next[]做了一个简单的分析,希望对大家有帮助,也希望大家能指出其中的错误和不足。由于直接贴文本格式难以控制,于是一部分内容被做成了图片。分析如下:

第一类next数组求解函数:

 

ContractedBlock.gif ExpandedBlockStart.gif 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数组求解函数:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 void KMP_next(char s[], int pre[]) {
 2     int i = 0, j = -1, n = (int)strlen(s);
 3     pre[0= -1;
 4     while(i <= n) {        //注意有i == n
 5         if(j == -1 || s[j] == s[i]) {
 6             i++; j++;
 7             pre[i] = j;
 8         }
 9         else j = pre[j];
10     }
11 }



POJ 3461 Oulipo这道题用两类KMP都可以过,但是代码上有一些细微的差别。本人比较喜欢第一类KMP,于是就贴第一类的代码了。
ContractedBlock.gif ExpandedBlockStart.gif POJ 3461 Oulipo
 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 const int MaxN = 1000010;
 5 
 6 char word[MaxN/10], txt[MaxN];
 7 int next[MaxN/10];
 8 
 9 void KMP_next(char b[], int pre[]) {
10     int n = (int)strlen(b), k;
11     pre[0= -1; k = -1;
12     for(int i = 1; i < n; i++) {
13         while(k > -1 && b[k+1!= b[i]) k = pre[k];
14         if(b[k+1== b[i]) k++;
15         pre[i] = k;
16     }
17 }
18 
19 int main() {
20     int n;
21     for(scanf("%d%*c"&n); n--;) {
22         gets(word); gets(txt);
23         KMP_next(word, next);
24         int cnt = 0, len = (int)strlen(word);
25         for(int i = 0, j = -1; txt[i]; ++i) {
26             while(j > -1 && word[j+1!= txt[i])
27                 j = next[j];
28             if(word[j+1== txt[i])
29                 j++;
30             if(j == len-1) {
31                 cnt++; j = next[j];
32             }
33         }
34         printf("%d\n", cnt);
35     }
36     return 0;
37 }

转载于:https://www.cnblogs.com/destinydesigner/archive/2009/10/17/1585063.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值