经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
BZOJ4566: [Haoi2016]找相同字符(后缀自动机)
来源:cnblogs  作者:自为风月马前卒  时间:2018/12/17 9:47:51  对本文有异议

题意

题目链接

Sol

直接在SAM上乱搞

枚举前缀,用SAM统计可以匹配的后缀,具体在匹配的时候维护和当前节点能匹配的最大值

然后再把parent树上的点的贡献也统计上,这部分可以爆跳parent树(假的,因为这题数据随机),也可以直接树形dp一波记下每个点被统计的次数

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. using namespace std;
  4. const int MAXN = 4e5 + 10;
  5. int N1, N2;
  6. char a[MAXN], b[MAXN];
  7. // struct SAM {
  8. int fa[MAXN], ch[MAXN][26], len[MAXN], siz[MAXN], tot, las, root, f[MAXN], g[MAXN];
  9. vector<int> v[MAXN];
  10. // SAM() {
  11. // root = las = tot = 1;
  12. // }
  13. void insert(int x) {
  14. int now = ++tot, pre = las; las = now; siz[now] = 1;
  15. len[now] = len[pre] + 1;
  16. for(; pre && !ch[pre][x]; pre = fa[pre]) ch[pre][x] = now;
  17. if(!pre) fa[now] = root;
  18. else {
  19. int q = ch[pre][x];
  20. if(len[pre] + 1 == len[q]) fa[now] = q;
  21. else {
  22. int ns = ++tot; fa[ns] = fa[q]; len[ns] = len[pre] + 1;
  23. memcpy(ch[ns], ch[q], sizeof(ch[q]));
  24. fa[q] = fa[now] = ns;
  25. for(; pre && ch[pre][x] == q; pre = fa[pre]) ch[pre][x] = ns;
  26. }
  27. }
  28. }
  29. void Build() {
  30. for(int i = 2; i <= tot; i++) v[fa[i]].push_back(i);
  31. }
  32. void dfs(int x, int opt) {
  33. for(int i = 0; i < v[x].size(); i++) {
  34. int to = v[x][i];
  35. dfs(to, opt);
  36. if(opt == 1) siz[x] += siz[to];
  37. if(opt == 2) f[x] += f[to] + g[to];
  38. }
  39. }
  40. // }sam;
  41. int main() {
  42. root = las = tot = 1;
  43. scanf("%s%s", a + 1, b + 1);
  44. N1 = strlen(a + 1); N2 = strlen(b + 1);
  45. for(int i = 1; i <= N1; i++) insert(a[i] - 'a');
  46. Build(); dfs(root, 1);
  47. int now = root, cur = 0; LL ans = 0;
  48. for(int i = 1; i <= N2; i++) {
  49. int x = b[i] - 'a';
  50. if(ch[now][x]) now = ch[now][x], cur++;
  51. else {
  52. while(!ch[now][x] && now) now = fa[now];
  53. if(!now) now = 1, cur = 0;
  54. else cur = len[now] + 1, now = ch[now][x];
  55. }
  56. ans += 1ll * (cur - len[fa[now]]) * siz[now];
  57. g[now]++;
  58. //int tmp = fa[now];
  59. //while(tmp != 1) ans += (len[tmp] - len[fa[tmp]]) * siz[tmp], tmp = fa[tmp];
  60. }
  61. dfs(root, 2);
  62. for(int i = 1; i <= tot; i++) ans += 1ll * (len[i] - len[fa[i]]) * siz[i] * f[i];
  63. cout << ans;
  64. return 0;
  65. }
  66. /*
  67. aa
  68. aa
  69. acb
  70. abc
  71. ababababba
  72. abbababab
  73. */
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号