一只只会后缀自动机却不会后缀数组的弱鸡做了一下HDU - 1403,结果SAM被卡内存了,然后学习了一下SA。

以下两道题都是求LCS,区别在于字符串长度。

参考blog:https://www.cnblogs.com/victorique/p/8480093.html

HDU - 1403

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <algorithm>
  5. #define rank Rank
  6. using namespace std;
  7. const int MAXN = 2e5+;
  8. char str[MAXN];
  9. int SA[MAXN], rank[MAXN], height[MAXN], sum[MAXN], tp[MAXN];
  10. //rank[i] 第i个后缀的排名, SA[i] 排名为i的后缀的位置, Height[i] 排名为i的后缀与排名为(i-1)的后缀的LCP
  11. //sum[i] 基数排序辅助数组, 存储小于i的元素有多少个, tp[i] rank的辅助数组(按第二关键字排序的结果),与SA意义一样
  12. bool cmp(int *f, int x, int y, int w){return f[x] == f[y] && f[x + w] == f[y + w];}
  13.  
  14. void get_SA(char *s, int n, int m)
  15. {
  16. for(int i = ; i < m; i++) sum[i] = ;
  17. for(int i = ; i < n; i++) sum[rank[i] = s[i]]++;
  18. for(int i = ; i < m; i++) sum[i] += sum[i - ];
  19. for(int i = n - ; i >= ; i--) SA[--sum[rank[i]]] = i;
  20. for(int len = ; len <= n; len <<= )
  21. {
  22. int p = ;
  23. for(int i = n - len; i < n; i++) tp[p++] = i;
  24. for(int i = ; i < n; i++)
  25. if(SA[i] >= len)
  26. tp[p++] = SA[i] - len;
  27. for(int i = ; i < m; i++) sum[i] = ;
  28. for(int i = ; i < n; i++) sum[rank[tp[i]]]++;
  29. for(int i = ; i < m; i++) sum[i] += sum[i - ];
  30. for(int i = n - ; i >= ; i--) SA[--sum[rank[tp[i]]]] = tp[i];
  31. swap(rank, tp);
  32. p = ;
  33. rank[SA[]] = ;
  34. for(int i = ; i < n; i++)
  35. rank[SA[i]] = cmp(tp, SA[i - ], SA[i], len) ? p - : p++;
  36. if(p >= n) break;
  37. m = p;
  38. }
  39. int k = ;
  40. n--;
  41. for(int i = ; i <= n; i++) rank[SA[i]] = i;
  42. for(int i = ; i < n; i++)
  43. {
  44. if(k) k--;
  45. int j = SA[rank[i] - ];
  46. while(s[i + k] == s[j + k]) k++;
  47. height[rank[i]] = k;
  48. }
  49. }
  50. int main()
  51. {
  52. while(~scanf("%s", str))
  53. {
  54. int len = strlen(str);
  55. str[len] = '';
  56. scanf("%s", str + len + );
  57. int n = strlen(str);
  58. str[n] = ; //末尾添加一个0
  59. get_SA(str, n + , 'z' + );
  60. int sol = ;
  61. for(int i = ; i < n; i++)
  62. {
  63. if(SA[i] > len && SA[i - ] < len) sol = max(sol, height[i]);
  64. if(SA[i] < len && SA[i - ] > len) sol = max(sol, height[i]);
  65. }
  66. printf("%d\n", sol);
  67. }
  68. return ;
  69. }

SPOJ - LCS

SA版本:

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <algorithm>
  5. #define rank Rank
  6. using namespace std;
  7. const int MAXN = 5e5+;
  8. char str[MAXN];
  9. int SA[MAXN], rank[MAXN], height[MAXN], sum[MAXN], tp[MAXN];
  10. //rank[i] 第i个后缀的排名, SA[i] 排名为i的后缀的位置, Height[i] 排名为i的后缀与排名为(i-1)的后缀的LCP
  11. //sum[i] 基数排序辅助数组, 存储小于i的元素有多少个, tp[i] rank的辅助数组(按第二关键字排序的结果),与SA意义一样
  12. bool cmp(int *f, int x, int y, int w){return f[x] == f[y] && f[x + w] == f[y + w];}
  13.  
  14. void get_SA(char *s, int n, int m)
  15. {
  16. for(int i = ; i < m; i++) sum[i] = ;
  17. for(int i = ; i < n; i++) sum[rank[i] = s[i]]++;
  18. for(int i = ; i < m; i++) sum[i] += sum[i - ];
  19. for(int i = n - ; i >= ; i--) SA[--sum[rank[i]]] = i;
  20. for(int len = ; len <= n; len <<= )
  21. {
  22. int p = ;
  23. for(int i = n - len; i < n; i++) tp[p++] = i;
  24. for(int i = ; i < n; i++)
  25. if(SA[i] >= len)
  26. tp[p++] = SA[i] - len;
  27. for(int i = ; i < m; i++) sum[i] = ;
  28. for(int i = ; i < n; i++) sum[rank[tp[i]]]++;
  29. for(int i = ; i < m; i++) sum[i] += sum[i - ];
  30. for(int i = n - ; i >= ; i--) SA[--sum[rank[tp[i]]]] = tp[i];
  31. swap(rank, tp);
  32. p = ;
  33. rank[SA[]] = ;
  34. for(int i = ; i < n; i++)
  35. rank[SA[i]] = cmp(tp, SA[i - ], SA[i], len) ? p - : p++;
  36. if(p >= n) break;
  37. m = p;
  38. }
  39. int k = ;
  40. n--;
  41. for(int i = ; i <= n; i++) rank[SA[i]] = i;
  42. for(int i = ; i < n; i++)
  43. {
  44. if(k) k--;
  45. int j = SA[rank[i] - ];
  46. while(s[i + k] == s[j + k]) k++;
  47. height[rank[i]] = k;
  48. }
  49. }
  50. int main()
  51. {
  52. while(~scanf("%s", str))
  53. {
  54. int len = strlen(str);
  55. str[len] = '';
  56. scanf("%s", str + len + );
  57. int n = strlen(str);
  58. str[n] = ; //末尾添加一个0
  59. get_SA(str, n + , 'z' + );
  60. int sol = ;
  61. for(int i = ; i < n; i++)
  62. {
  63. if(SA[i] > len && SA[i - ] < len) sol = max(sol, height[i]);
  64. if(SA[i] < len && SA[i - ] > len) sol = max(sol, height[i]);
  65. }
  66. printf("%d\n", sol);
  67. }
  68. return ;
  69. }

SAM版本:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int kind=;
  4. const int maxn=;
  5. struct state
  6. {
  7. state *Next[kind],*link;
  8. int len;
  9. state()
  10. {
  11. link=;
  12. len=;
  13. memset(Next,,sizeof(Next));
  14. }
  15. };
  16. int sz;
  17. state st[maxn*+];
  18. inline state* newnode(int len = )
  19. {
  20. memset(st[sz].Next,,sizeof(st[sz].Next));
  21. st[sz].link=;
  22. st[sz].len=len;
  23. return &st[sz++];
  24. }
  25. state *root,*last;
  26. void extend(int w)
  27. {
  28. state* p=last;
  29. state* cur=newnode(p->len+);
  30. while(p&&p->Next[w]==)
  31. {
  32. p->Next[w]=cur;
  33. p=p->link;
  34. }
  35. if(p)
  36. {
  37. state* q=p->Next[w];
  38. if(p->len+==q->len)
  39. cur->link=q;
  40. else
  41. {
  42. state* clone=newnode(p->len+);
  43. memcpy(clone->Next,q->Next,sizeof(q->Next));
  44. clone->link=q->link;
  45. q->link=clone;
  46. cur->link=clone;
  47. while(p&&p->Next[w]==q)
  48. {
  49. p->Next[w]=clone;
  50. p=p->link;
  51. }
  52. }
  53. }
  54. else cur->link=root;
  55. last=cur;
  56. }
  57. string keyword;
  58. int main()
  59. {
  60. ios::sync_with_stdio(false);
  61. while(cin>>keyword)
  62. {
  63. sz=;
  64. int ans=;
  65. root=newnode();
  66. last=root;
  67. for(int i=;i<keyword.size();i++)
  68. extend(keyword[i]-'a');
  69. cin>>keyword;
  70. state *p=root;
  71. int tmp=;
  72. for(int i=;i<keyword.size();i++)
  73. {
  74. if(p->Next[keyword[i]-'a'])
  75. {
  76. tmp++;
  77. p=p->Next[keyword[i]-'a'];
  78. }
  79. else
  80. {
  81.  
  82. while(p&&!p->Next[keyword[i]-'a'])
  83. p=p->link;
  84. if(!p)
  85. p=root;
  86. if(p->Next[keyword[i]-'a'])
  87. {
  88. tmp=p->len+;
  89. p=p->Next[keyword[i]-'a'];
  90. }
  91. else
  92. tmp=;
  93. }
  94. ans=max(ans,tmp);
  95. }
  96. cout<<ans<<endl;
  97. }
  98. return ;
  99. }

后缀数组(SA)学习记录的更多相关文章

  1. 后缀数组SA学习笔记

    什么是后缀数组 后缀数组\(sa[i]\)表示字符串中字典序排名为\(i\)的后缀位置 \(rk[i]\)表示字符串中第\(i\)个后缀的字典序排名 举个例子: ababa a b a b a rk: ...

  2. 后缀数组SA入门(史上最晦涩难懂的讲解)

    参考资料:victorique的博客(有一点锅无伤大雅,记得看评论区),$wzz$ 课件(快去$ftp$%%%),$oi-wiki$以及某个人的帮助(万分感谢!) 首先还是要说一句:我不知道为什么我这 ...

  3. 后缀数组(SA)总结

    后缀数组(SA)总结 这个东西鸽了好久了,今天补一下 概念 后缀数组\(SA\)是什么东西? 它是记录一个字符串每个后缀的字典序的数组 \(sa[i]\):表示排名为\(i\)的后缀是哪一个. \(r ...

  4. bzoj3796(后缀数组)(SA四连)

    bzoj3796Mushroom追妹纸 题目描述 Mushroom最近看上了一个漂亮妹纸.他选择一种非常经典的手段来表达自己的心意——写情书.考虑到自己的表达能力,Mushroom决定不手写情书.他从 ...

  5. [笔记]后缀数组SA

    参考资料这次是真抄的: 1.后缀数组详解 2.后缀数组-学习笔记 3.后缀数组--处理字符串的有力工具 定义 \(SA\)排名为\(i\)的后缀的位置 \(rk\)位置为\(i\)的后缀的排名 \(t ...

  6. 浅谈后缀数组SA

    这篇博客不打算讲多么详细,网上关于后缀数组的blog比我讲的好多了,这一篇博客我是为自己加深印象写的. 给你们分享了那么多,容我自私一回吧~ 参考资料:这位dalao的blog 一.关于求Suffix ...

  7. 【字符串】后缀数组SA

    后缀数组 概念 实际上就是将一个字符串的所有后缀按照字典序排序 得到了两个数组 \(sa[i]\) 和 \(rk[i]\),其中 \(sa[i]\) 表示排名为 i 的后缀,\(rk[i]\) 表示后 ...

  8. 洛谷.3809.[模板]后缀排序(后缀数组 倍增) & 学习笔记

    题目链接 //输出ht见UOJ.35 #include<cstdio> #include<cstring> #include<algorithm> const in ...

  9. 后缀数组SA

    复杂度:O(nlogn) 注:从0到n-1 const int maxn=1e5; char s[maxn]; int sa[maxn],Rank[maxn],height[maxn],rmq[max ...

  10. 洛谷2408不同字串个数/SPOJ 694/705 (后缀数组SA)

    真是一个三倍经验好题啊. 我们来观察这个题目,首先如果直接整体计算,怕是不太好计算. 首先,我们可以将每个子串都看成一个后缀的的前缀.那我们就可以考虑一个一个后缀来计算了. 为了方便起见,我们选择按照 ...

随机推荐

  1. iphone开发笔记

    1.uiimage图片拉伸 - (void)stretchBackgroundImage { //UIImage *originalImage = [[self backgroundImageForS ...

  2. linux 命令——5 rm(转)

    昨天学习了创建文件和目录的命令mkdir ,今天学习一下linux中删除文件和目录的命令: rm命令.rm是常用的命令,该命令的功能为删除一个目录中的一个或多个文件或目录,它也可以将某个目录及其下的所 ...

  3. C#Json数据交互

    问题:写项目时,难免会遇到前台和后台要进行数据交换,往前台传一个对象或一个对象集,往后台传一个对象,一个对象集.怎么传,你当然不能直接去传递一个对象或对象集,我们可以利用JSON数据相互之间传值. J ...

  4. c语言中--typeof--关键字用法

    C语言中 typeof 关键字是用来定义变量数据类型的.在linux内核源代码中广泛使用. 下面是Linux内核源代码中一个关于typeof实例: #define min(x, y) ({ \ typ ...

  5. 通过rsync+inotify实现数据实时备份

    rsync的优点与不足 与传统的cp,scp,tar,备份方式相比,rsync具有安全性高备份迅速支持增量备份的优点,可以满足对实时性要求不高的需求,例如定期备份文件服务器数据到远端服务器,但是,当数 ...

  6. linux几种文件传输方式

    本文记录linux系统中文件传输的多种方式,留作备忘.linux中文件传输的方式有ftp,scp,rsync,rz,sz等,但各个工具的功能又有所区别: FTP : FTP是文件服务器,可实现文件的上 ...

  7. Visual Studio 2017 初次体验

    在初次体验中遇到以下问题以及技巧 1. 在出现红色波浪线时为出现错误语法,将鼠标移动到相应位置可以获得相关错误信息 2.在编写代码过程中,行号上出现的小黄灯可以有提示信息 3.List 与 Array ...

  8. 如何查看连接到手机热点的ip地址

    因为最近玩树莓派,需要手机做热点,然后用树莓派连接到这个热点上,苦于不知道树莓派被分配了什么样的ip地址,经过一番探索,我发现了两种办法, 安装一个 android terminal( 安卓命令行), ...

  9. 用jq给img添加error事件

    <img src="xxxx.jpg" alt="" /> <script> $(document).ready(function(){ ...

  10. Android Studio 3.0 安装注意点

    在安装Android studio 3.0+ 时候,会遇到默认不带Android SDK 的问题. 在启动Android studio 后,会提示让选择SDK目录,选择下载目录,对应的去下载 那么问题 ...