Chinaunix首页 | 论坛 | 博客
  • 博客访问: 121634
  • 博文数量: 49
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: -15
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-03 22:22
个人简介

小楼一夜听春雨

文章分类
文章存档

2017年(1)

2016年(2)

2015年(5)

2014年(21)

2013年(5)

2012年(7)

2010年(6)

2009年(2)

我的朋友

分类: PHP

2009-10-08 00:29:23

问题:设一个字符串,求一最大公有子串,使得该子串在字符串的头部和尾部都存在,且是最长的。
 
分析:记该字符串为a = a[1]a[2]...a[n],
      数组len = len[1]len[2]...len[n], 代表前i个字符所组成的最大公有子串的长度;
      比如,len[5],就表示前5个字符所组成的串的最大公有子串的长度。
      如果不存在最大公有子串,那么len[i]=0,且记len[1]=0
      那么如何求得len[i](1      记k=len[i-1]
      如果a[k+1]=a[i],那么显然,len[i]=k+1;
      如果a[k+1]!=a[i],那么len[i]或者大于k+1, 或者小于k+1
      假如len[i]>k+1, 那就意味着len[i-1]>k,这是不可能的
      所以只有可能是len[i]      现在假设该最大公有子串长度为x+1,那么可以证明串a[1..x]是串a[1..k]的一个公有子串
      事实上,因为a[1..x]=a[i-x..i-1], 而a[i-x..i-1]=a[k-x+1..k]
      从而,有a[1..x]=a[k-x+1..k],所以串a[1..x]是串a[1..k]的一个公有子串
      知道了这一点,就意味着如果存在最大公有子串,
      那么该公有子串一定是串a[1..k]中的公有子串再接一个字符a[i]
      所以我们可以从串a[1..k]的最大公有子串找起,一直往回找,直到找到或不存在为止。
 
算法设计与实现:
输入:字符串pattern
输出:一个整数数组,与pattern同长度, 其第i个值代表pattern前i个字符所组成的最大公有子串的长度

  1. int *compute_prefix(const char *pattern) {
  2.     int *prefix;
  3.     int i, k, size;

  4.     assert(pattern);
  5.     size = strlen(pattern);
  6.     prefix = malloc(size * sizeof(int));
  7.     memset(prefix, '\0', size * sizeof(int));
  8.     for (i = 1; i < size; i++) {
  9.         k = prefix[i-1];
  10.         while (1) {
  11.             if (pattern[i] == pattern[k]) {
  12.                 prefix[i] = k+1;
  13.                 break;
  14.             }
  15.             if (k == 0) break;
  16.             k = prefix[k-1];
  17.         }
  18.     }
  19.     return prefix;
  20. }
此算法是实现kmp模式匹配的基础
阅读(1087) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~