POJ1743 Musical Theme

要找长度\(\ge 5\)且出现次数\(\ge 2\)并且第一次出现和最后一次出现不重叠的最长子串。

题目条件中,如果对于两个串,在一个串的每个数上都加上相同的数之后可以得到另一个串,那么这个两个串可以被是相同的。

首先我们先得到差分数组,然后要求的就是差分数组中长度\(\ge 4\)且出现次数\(\ge 2\)并且第一次出现和最后一次出现不重叠的最长子串

我们需要知道的是每个等价类中终点的最左端和最右端的位置,即(\(firstpos,lastpos\)),每次新加入一个字符所得到的等价类其\(firstpos\)和\(lastpos\)必然为当前的下标,当构造完\(SAM\)之后,由于\(parent\)树的性质,\(link[u]\)所表示的等价类必然是\(u\)所表示的等价类的后缀,所以可以得到:\(lastpos[u] = max_{v\in children} lastpos[v]\)其中\(v\)是\(u\)在\(parent\)树中的儿子,而\(firstpos\)必然一直保持不变。

可以用拓扑排序然后倒序遍历来代替建\(parent\)树然后\(dfs\),拓扑排序即为按\(len\)排序,用基数排序即可

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<cmath>
  5. #include<set>
  6. #include<map>
  7. #include<vector>
  8. #include<queue>
  9. #include<string>
  10. #include<algorithm>
  11. #include<stack>
  12. using namespace std;
  13. void ____(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); }
  14. const int MAXN = 1e5+7;
  15. int n,A[MAXN];
  16. struct SAM{
  17. int len[MAXN],link[MAXN],firstpos[MAXN],lastpos[MAXN],ch[MAXN][180],tot,last,cnt[MAXN],c[MAXN],sa[MAXN];
  18. void init(){ link[tot = last = cnt[0] = len[0] = 0] = -1; memset(ch[0],0,sizeof(ch[0])); }
  19. void extend(int x){
  20. int np = ++tot, p = last; firstpos[tot] = lastpos[tot] = len[tot] = len[last] + 1;
  21. memset(ch[tot],0,sizeof(ch[tot])); cnt[tot] = 1;
  22. while(p!=-1 and !ch[p][x]){
  23. ch[p][x] = np;
  24. p = link[p];
  25. }
  26. if(p==-1) link[np] = 0;
  27. else{
  28. int q = ch[p][x];
  29. if(len[p]+1==len[q]) link[np] = q;
  30. else{
  31. int clone = ++tot;
  32. cnt[clone] = 0;
  33. firstpos[clone] = firstpos[q];
  34. lastpos[clone] = lastpos[q];
  35. len[clone] = len[p] + 1;
  36. for(int i = 0; i < 180; i++) ch[clone][i] = ch[q][i];
  37. link[clone] = link[q];
  38. while(p!=-1 and ch[p][x]==q){
  39. ch[p][x] = clone;
  40. p = link[p];
  41. }
  42. link[np] = link[q] = clone;
  43. }
  44. }
  45. last = np;
  46. }
  47. int solve(){
  48. for(int i = 0; i <= n; i++) c[i] = 0;
  49. for(int i = 0; i <= tot; i++) c[len[i]]++;
  50. for(int i = 1; i <= n; i++) c[i] += c[i-1];
  51. for(int i = tot; i >= 0; i--) sa[c[len[i]]--] = i;
  52. int ret = 0;
  53. for(int i = tot+1; i >= 1; i--){ //这里要注意,基数排序的时候是0~tot,所以排名最后的是tot+1
  54. int u = sa[i];
  55. cnt[link[u]] += cnt[u];
  56. lastpos[link[u]] = max(lastpos[link[u]],lastpos[u]);
  57. ret = max(ret,min(len[u] + 1,lastpos[u]-firstpos[u]));
  58. }
  59. if(ret<5) ret = 0;
  60. return ret;
  61. }
  62. }sam;
  63. void solve(){
  64. for(int i = 1; i <= n; i++) scanf("%d",&A[i]);
  65. for(int i = 1; i < n; i++) A[i] = A[i+1] - A[i] + 88;
  66. sam.init(); for(int i = 1; i < n; i++) sam.extend(A[i]);
  67. printf("%d\n",sam.solve());
  68. }
  69. int main(){
  70. while(scanf("%d",&n)!=EOF and n) solve();
  71. return 0;
  72. }

POJ 1743 Musical Theme【SAM】的更多相关文章

  1. POJ 1743 Musical Theme 【后缀数组 最长不重叠子串】

    题目冲鸭:http://poj.org/problem?id=1743 Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Su ...

  2. Poj 1743——Musical Theme——————【后缀数组,求最长不重叠重复子串长度】

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22499   Accepted: 7679 De ...

  3. poj 1743 Musical Theme【后缀自动机】

    不是很神的一道题,一般. 先差分,最后答案需要+1. 一个right集的len即为该right集的最长相同后缀,考虑到不能重复,所以处理一下该right集的最大与最小的ri,最后答案ans=max(a ...

  4. poj 1743 Musical Theme【二分+SA】

    差分,然后二分长度mid,判断是把height按照min不小于mid分组,取最大最小的sa位置看是否>=mid即可,注意差分后最后答案要+1 #include<iostream> # ...

  5. POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)(转)

    永恒的大牛,kuangbin,膜拜一下,Orz 链接:http://www.cnblogs.com/kuangbin/archive/2013/04/23/3039313.html Musical T ...

  6. poj 1743 Musical Theme(最长重复子串 后缀数组)

    poj 1743 Musical Theme(最长重复子串 后缀数组) 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复 ...

  7. Poj 1743 Musical Theme (后缀数组+二分)

    题目链接: Poj  1743 Musical Theme 题目描述: 给出一串数字(数字区间在[1,88]),要在这串数字中找出一个主题,满足: 1:主题长度大于等于5. 2:主题在文本串中重复出现 ...

  8. POJ 1743 Musical Theme 后缀数组 最长重复不相交子串

    Musical ThemeTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=1743 Description ...

  9. POJ 1743 Musical Theme(后缀数组+二分答案)

    [题目链接] http://poj.org/problem?id=1743 [题目大意] 给出一首曲子的曲谱,上面的音符用不大于88的数字表示, 现在请你确定它主旋律的长度,主旋律指的是出现超过一次, ...

随机推荐

  1. 【剑指 Offer】11.旋转数组的最小数字

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的 ...

  2. python学习笔记 | strftime()格式化输出时间

    time模块 import time t = time.strftime("%Y-%m-%d %H:%M:%S") print(t) datetime模块 import datet ...

  3. CSS 奇思妙想边框动画

    今天逛博客网站 -- shoptalkshow,看到这样一个界面,非常有意思: 觉得它的风格很独特,尤其是其中一些边框. 嘿嘿,所以来一篇边框特辑,看看运用 CSS,可以在边框上整些什么花样. bor ...

  4. 【IMPDP】ORA-31655

    出现ora-31655错误的情况是因为不是同一个schema,导致的问题产生 解决的方法; 在导入语句最后添加上remap_schema=old:new 着old是原schema,也就是导出的用户名, ...

  5. Sqli - Labs 靶场笔记(一)

    Less - 1: 页面: URL: http://127.0.0.1/sqli-labs-master/Less-1/ 测试: 1.回显正常,说明不是数字型注入, http://127.0.0.1/ ...

  6. windows下部署Grafana +prometheus平台监控

      1.Prometheus简介 Prometheus基于Golang编写,编译后的软件包,不依赖于任何的第三方依赖.用户只需要下载对应平台包,解压并且添加基本的配置即可正常启Prometheus S ...

  7. 1V转5V芯片,三个元件即可组成完整的稳压方案

    1V低电压要转成5V的电压,需要1V转5V的芯片,由于1V输入,所以不需要指望能输出多大的电流,压差和1V的供电电压意味着供电电流也是无法做大的了.一般1V转5V的输出电流在0MA-100mA,一般6 ...

  8. 图解 ECDHE 密钥交换算法

    HTTPS 常用的密钥交换算法有两种,分别是 RSA 和 ECDHE 算法. 其中,RSA 是比较传统的密钥交换算法,它不具备前向安全的性质,因此现在很少服务器使用的.而 ECDHE 算法具有前向安全 ...

  9. pymysql模块使用介绍

    pymysql ​ 我们要学的pymysql就是用来在python程序中如何操作mysql,本质上就是一个套接字客户端,只不过这个套接字客户端是在python程序中用的,既然是客户端套接字,应该怎么用 ...

  10. Django-初阶实例

    调用本地css文件的方法 setting.py里面的内容 import os # Build paths inside the project like this: os.path.join(BASE ...