首页 考试吧论坛 Exam8视线 考试商城 网络课程 模拟考试 考友录 实用文档 求职招聘 论文下载
2011中考 | 2011高考 | 2012考研 | 考研培训 | 在职研 | 自学考试 | 成人高考 | 法律硕士 | MBA考试
MPA考试 | 中科院
四六级 | 职称英语 | 商务英语 | 公共英语 | 托福 | 雅思 | 专四专八 | 口译笔译 | 博思 | GRE GMAT
新概念英语 | 成人英语三级 | 申硕英语 | 攻硕英语 | 职称日语 | 日语学习 | 法语 | 德语 | 韩语
计算机等级考试 | 软件水平考试 | 职称计算机 | 微软认证 | 思科认证 | Oracle认证 | Linux认证
华为认证 | Java认证
公务员 | 报关员 | 银行从业资格 | 证券从业资格 | 期货从业资格 | 司法考试 | 法律顾问 | 导游资格
报检员 | 教师资格 | 社会工作者 | 外销员 | 国际商务师 | 跟单员 | 单证员 | 物流师 | 价格鉴证师
人力资源 | 管理咨询师考试 | 秘书资格 | 心理咨询师考试 | 出版专业资格 | 广告师职业水平
驾驶员 | 网络编辑
卫生资格 | 执业医师 | 执业药师 | 执业护士
会计从业资格考试会计证) | 经济师 | 会计职称 | 注册会计师 | 审计师 | 注册税务师
注册资产评估师 | 高级会计师 | ACCA | 统计师 | 精算师 | 理财规划师 | 国际内审师
一级建造师 | 二级建造师 | 造价工程师 | 造价员 | 咨询工程师 | 监理工程师 | 安全工程师
质量工程师 | 物业管理师 | 招标师 | 结构工程师 | 建筑师 | 房地产估价师 | 土地估价师 | 岩土师
设备监理师 | 房地产经纪人 | 投资项目管理师 | 土地登记代理人 | 环境影响评价师 | 环保工程师
城市规划师 | 公路监理师 | 公路造价师 | 安全评价师 | 电气工程师 | 注册测绘师 | 注册计量师
缤纷校园 | 实用文档 | 英语学习 | 作文大全 | 求职招聘 | 论文下载 | 访谈 | 游戏
您现在的位置: 考试吧(Exam8.com) > 软件水平考试 > 复习资料 > 程序员资料 > 正文

2011年软考程序员考试复习笔试知识点整理(16)

来源:考试吧Exam8.com) 2011-4-16 19:14:48 考试吧:中国教育培训第一门户 模拟考场
考试吧提供了“2011年软考程序员考试复习笔试知识点整理”,供考生参考。

  更多:2011年软考程序员考试复习笔试知识点整理汇总

  20、后缀数组

  (1)什么是后缀数组呢?

  直观来说,后缀数组是记录一个字符串的后缀的排名的数组,什么是后缀呢,设一个字符串的长度是len(我们约定字符串下标从0开始,所以到len-1结束,比较符合我们日常编程习惯),某一位置i的后缀的就是从i开始到len-1结束的字符串,用suffix(i)表示,即对字符串s来说,suffix(i) =s[i,i+1....len-1],可以发现不同的后缀按字典序排列的名词是不一样的(什么是字典序都应该知道吧),记录这些后缀按字典序排好的结果的数组就叫后缀数组,一般用sa[]表示,网络上对sa[]的标准定义为:

  后缀数组:后缀数组SA 是一个一维数组,它保存1..n 的某个排列SA[1],SA[2],……,SA[n],并且保证Suffix(SA[i])< Suffix(SA[i+1]),1≤i

  另外还要用到排名数组,即某一位置的后缀在所有后缀中的排名的数组,一般用Rank[]表示,容易发现Rank[sa[i]]=i。

  名次数组:名次数组Rank[i]保存的是Suffix(i)在所有后缀中从小到大排列的“名次”。

  简单的说,后缀数组是“排第几的是谁?”,名次数组是“你排第几?”。

  知道了这些定义,剩下的就是如何构建后缀数组了,可以按照定义来构建,把每个后缀当做一个字符串,用全速排序来排序,不过那样的时间复杂度为O(n*n),一般用来构建后缀数组用的是倍增算法(Doubling Algorithm),说到倍增算法,就要说到k-前缀的定义,字符串u的k-前缀就是u的从0开始到k-1的字串,u长度不足k时就是整个字符串u,这样一来我们在比较串s的两个位置i,j的后缀的2k-前缀时,就是比较两个后缀的k-前缀和两个后缀位置+k的k-前缀,显然当k=1时就是对整个串的单字符进行排序,复杂度O(nlogn),当k>=2时对已排好的k-前缀进行排序,用快排,复杂度O(nlogn),用基数排序,复杂度O(n),容易发现k是2倍增的。所以整个过程的时间复杂度就是O(nlongn)。

  倍增算法构建sa[]的代码如下:

  #definemax 10000

  intRx[max],Ry[max],rx[max];

  intcmp(int *y,int a,int b,int l)

  {

  return y[a] == y[b] && y[a+l] +y[b+l];

  }

  //对于串约定最后一位是小于串中其他任何元素的元素,这样cmp的时候就不用担心y[a+l]

  //越界了,因为y[a]= y[b]就暗含了他们长度相等,都没有包含最后一位。

  voidget_sa(char *s,int *sa)

  {

  int len = strlen(s),*Rank_x = Rx,*Rank_y =Ry,bar[max],*result_x = rx;

  int i,j,k,p,*t,m=255;

  for (i = 0; i<= m; i++)//对字符排序不会超过255,根据实际情况m值自定

  bar[i] = 0;

  for (i = 0; i< len; i++) bar[Rank_x[i] =s[i]]++;

  for (i = 1; i<= m; i++) bar[i] +=bar[i-1];

  for (i = len-1; i>= 0; i--)sa[--bar[Rank_x[i]]] = i;

  //这段代码用到桶排序思想,就是先进桶,再从不同桶里一个一个往外倒

  //sa[]保存的是1-前缀排序结果,Rank_x[]保存的是1-前缀时的各位置的排名

  for (k = 1,p = 1; p < len; k *= 2, m = p)

  {

  for (p = 0,i = len - k; i < len;i++) Rank_y[p++] = i;

  for (i = 0; i< len; i++) if (sa[i]>= k) Rank_y[p++] = sa[i] - k;

  //这段代码对1-前缀时做第二关键字排序

  for (i = 0; i< len; i++) result_x[i]= Rank_x[Rank_y[i]];

  for (i = 0; i<= m; i++) bar[i] =0;

  for (i = 0; i< len; i++)bar[result_x[i]]++;

  for (i = 1; i<= m; i++) bar[i] +=bar[i-1];

  for (i = len-1; i>= 0; i--)sa[--bar[result_x[i]]] = Rank_y[i];

  //又用到了一次桶排序,注意体会,是在对第二关键字排好序的序列上对

  //第一关键字进行桶排序求得了新的sa[],result_x[]保存的是关于第二关键字

  //排好序的序列的第一关键字排名,为桶排序做好准备

  for (t = Rank_x,Rank_x = Rank_y,Rank_y= t,p = 1,Rank_x[sa[0]]= 0,i = 1; i

  Rank[sa[i]] =cmp(Rank_y,sa[i],sa[i-1],k)?p-1:p++;

  //求新的名次数组,可以发现名次可能一样,当名次各不一样时就是排序完成时。

  }

  }

1 2 3 4 5 下一页
  相关推荐:

  软考程序员考试历年真题重点题总结及答案

  2011年上半年软考报名时间及方式汇总

  软考程序员考试历年真题汇总(2007年-2010年)

文章搜索
软件水平考试栏目导航
版权声明:如果软件水平考试网所转载内容不慎侵犯了您的权益,请与我们联系800@exam8.com,我们将会及时处理。如转载本软件水平考试网内容,请注明出处。