怪盗基德的挑战书

Problem Description
  “在树最美丽的那天,当时间老人再次把大钟平均分开时,我会降临在灯火之城的金字塔前,带走那最珍贵的笑容。”这是怪盗基德盗取巴黎卢浮宫的《蒙娜丽莎的微笑》这幅画时,挑战书上的内容。
  但这次,怪盗基德的挑战书上出现了一串串小写字母“aaab sdfeeddd...”。柯南以小学生的眼睛,超凡高中生的头脑,快速统计各种字母频率,字符串长度,并结合挑战书出现的时间等信息,试图分析怪盗基德的意图。最后,他将线索锁定在字符串的循环次数上。并且进一步推理发现,从字符串的第一位开始,到第i位,形成该字符串的子串(c1, c2, c3 ... ci )。对于某一子串ci在该字符串中出现的次数记为ki,则全部子串的循环次数总和AIM = k1 + k2 + ... + ki + ... + kn,柯南发现,AIM恰好对应一个ASCII码!所以,只要把挑战书上的字符串转变成数字,再找到对应的ASCII码,就可以破解这份挑战书了!
  现在,你的任务就是把字符串转变成对应数字,因为ASCII码以及扩展ASCII码全部只有256个,所以,本题只要把结果对256取余即可。
Input
输入有多组测试数据;
每组测试数据只有一个字符串,由各种小写字母组成,中间无空格。
字符串的长度为L(0 < L <= 100000)。
Output
请计算并输出字符串的AIM值,每组数据输出一行。
Sample Input
aaa
abab
 
Sample Output
6
6
 
 
【题意】
  给一个串s,求s的每个前缀出现次数之和。
 
【分析】

  用后缀数组求的话,就是求出每个后缀和最长的后缀的公共前缀长度就可以了。

  就是rank[1]的位置往两边找。

代码如下:

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. #include<queue>
  7. using namespace std;
  8. #define INF 0xfffffff
  9. #define Maxl 100010
  10. #define Mod 256
  11.  
  12. int k,la;
  13. char a[Maxl],b[Maxl];
  14. int c[Maxl];
  15. int cl;
  16.  
  17. int sa[Maxl],rk[Maxl],Rs[Maxl],wr[Maxl],y[Maxl];
  18. //sa -> 排名第几的是谁
  19. //rk -> i的排名
  20. //Rs数值小于等于i的有多少个
  21. //y -> 第二关键字排名第几的是谁(类似sa)
  22. int height[Maxl];
  23.  
  24. int mymin(int x,int y) {return x<y?x:y;}
  25.  
  26. void get_sa(int m)
  27. {
  28. memcpy(rk,c,sizeof(rk));
  29. for(int i=;i<=m;i++) Rs[i]=;
  30. for(int i=;i<=cl;i++) Rs[rk[i]]++;
  31. for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
  32. for(int i=cl;i>=;i--) sa[Rs[rk[i]]--]=i;
  33.  
  34. int ln=,p=;
  35. while(p<cl)
  36. {
  37. int k=;
  38. for(int i=cl-ln+;i<=cl;i++) y[++k]=i;
  39. for(int i=;i<=cl;i++) if(sa[i]>ln) y[++k]=sa[i]-ln;
  40. for(int i=;i<=cl;i++) wr[i]=rk[y[i]];
  41.  
  42. for(int i=;i<=m;i++) Rs[i]=;
  43. for(int i=;i<=cl;i++) Rs[wr[i]]++;
  44. for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
  45. for(int i=cl;i>=;i--) sa[Rs[wr[i]]--]=y[i];
  46.  
  47. for(int i=;i<=cl;i++) wr[i]=rk[i];
  48. for(int i=cl+;i<=cl+ln;i++) wr[i]=;
  49. p=;rk[sa[]]=;
  50. for(int i=;i<=cl;i++)
  51. {
  52. if(wr[sa[i]]!=wr[sa[i-]]||wr[sa[i]+ln]!=wr[sa[i-]+ln]) p++;
  53. rk[sa[i]]=p;
  54. }
  55. m=p,ln*=;
  56. }
  57. sa[]=rk[]=;
  58. }
  59.  
  60. void get_he()
  61. {
  62. int kk=;
  63. for(int i=;i<=cl;i++)
  64. {
  65. int j=sa[rk[i]-];
  66. if(kk) kk--;
  67. while(c[i+kk]==c[j+kk]&&i+kk<=cl&&j+kk<=cl) kk++;
  68. height[rk[i]]=kk;
  69. }
  70. }
  71.  
  72. void ffind()
  73. {
  74. int ans=,minn=INF;
  75. ans+=cl;
  76. for(int i=rk[];i>=;i--)
  77. {
  78. minn=mymin(minn,height[i]);
  79. ans=(ans+minn)%Mod;
  80. }minn=INF;
  81. for(int i=rk[]+;i<=cl;i++)
  82. {
  83. minn=mymin(minn,height[i]);
  84. ans=(ans+minn)%Mod;
  85. }
  86. printf("%d\n",ans);
  87. }
  88.  
  89. int main()
  90. {
  91. while(scanf("%s",a)!=EOF)
  92. {
  93. cl=strlen(a);
  94. for(int i=;i<cl;i++) c[i+]=a[i]-'a'+;
  95. get_sa();
  96. get_he();
  97. ffind();
  98. }
  99. return ;
  100. }

[HDU4522]

2016-07-17 15:50:30

【HDU4552】 怪盗基德的挑战书(后缀数组)的更多相关文章

  1. HDU - 4552 怪盗基德的挑战书 (后缀数组)

    Description "在树最漂亮的那天,当时间老人再次把大钟平均分开时,我会降临在灯火之城的金字塔前.带走那最珍贵的笑容."这是怪盗基德盗取巴黎卢浮宫的<蒙娜丽莎的微笑& ...

  2. 后缀数组的倍增算法(Prefix Doubling)

    后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...

  3. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  4. BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]

    1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1383  Solved: 582[Submit][St ...

  5. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

  6. POJ1743 Musical Theme [后缀数组]

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 27539   Accepted: 9290 De ...

  7. 后缀数组(suffix array)详解

    写在前面 在字符串处理当中,后缀树和后缀数组都是非常有力的工具. 其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料. 其实后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现, ...

  8. 【UOJ #35】后缀排序 后缀数组模板

    http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...

  9. 【BZOJ-2119】股市的预测 后缀数组

    2119: 股市的预测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 334  Solved: 154[Submit][Status][Discuss ...

随机推荐

  1. pcap文件格式

      pcap文件格式 pcap文件格式是bpf保存原始数据包的格式,很多软件都在使用,比如tcpdump.wireshark等等,了解pcap格式可以加深对原始数据包的了解,自己也可以手工构造任意的数 ...

  2. Python教程:操作数据库,MySql的安装详解

    各位志同道合的同仁请点击上方关注 本教程是基于Python语言的深入学习.本次主要介绍MySql数据库软件的安装.不限制语言语法,对MySql数据库安装有疑惑的各位同仁都可以查看一下. 如想查看学习P ...

  3. jQuery模拟页面加载进度条

    因为我们无法通过任何方法获取整个页面的大小和当前加载了多少,所以想制作一个加载进度条的唯一办法就是模拟.那要怎么模拟呢? 我们知道,页面是从上往下执行的,也就是说我们可以大致估算出在页面的某个位置加载 ...

  4. 多维数组遍历PHP

    原文出处 <?php /* * ------------------------------------------------- * Author : nowamagic * Url : ww ...

  5. 深入理解自定义ListView

    深入理解自定义ListView ListView原理 他是一个系统的原生控件,用列表的形式来显示内容.如果内容过过有1000条左右,我们可以通过手势的上下滑动来查看数据.ListView也不是爆出OO ...

  6. 个人博客设计:创建Sql数据库操作类。

    整体的博客框架如下 数据库操作java类如下 package com.yxq.dao; import java.sql.Connection; import java.sql.DriverManage ...

  7. 什么是WordPress?

    (今天由于好友 肖知虎的 的需求 , 我开始了帮助小虎建站的需求, 就这样开始学习了Wordpress.  这些文章就是为了记录这些我在学习过程当中的心得,和记录下来的文字而已) 什么是WordPre ...

  8. java中获得IP地址

    public class IPTest { public static void main(String[] args) { try{ // 获取计算机名 String name = InetAddr ...

  9. Javascript基础学习(2)_表达式和运算符

    1.==和===的区别(!=和!==是相反的比较) 它们采用了同一性的两个不同定义.==是相等性,===是等同性. ①“===”进行两个值的比较 两个值的类型不同,就不相等 两个值是数字,并且值相同, ...

  10. C#调用ActiveX控件

    背景:最近项目中需要用到ActiveX控件,项目是在.Net平台下开发的.因此就直接在项目中添加了对ActiveX控件的引用,添加引用成功.在代码中实例化类的实例也没有问题,但在调用其方法或属性时总是 ...