【BZOJ4566】找相同字符(后缀数组)

题面

BZOJ

题解

后缀数组的做法,应该不是很难想

首先看到两个不同的串,当然是接在一起求\(SA,height\)

那么,考虑一下暴力

在两个串各枚举一个后缀,他们的\(lcp\)就是对答案产生的贡献

现在优化一下,按照\(SA\)的顺序枚举来处理\(lcp\)

利用一个单调栈维护一下,每次记录一下前面有多少个的贡献和当前答案一样就好啦

只是有点难写。。。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<set>
  8. #include<map>
  9. #include<vector>
  10. #include<queue>
  11. using namespace std;
  12. #define MAX 440000
  13. #define ll long long
  14. int n,gr[MAX];
  15. int SA[MAX],hg[MAX],rk[MAX];
  16. int a[MAX],t[MAX],x[MAX],y[MAX];
  17. bool cmp(int i,int j,int k){return y[i]==y[j]&&y[i+k]==y[j+k];}
  18. void GetSA()
  19. {
  20. int m=50;
  21. for(int i=1;i<=n;++i)t[x[i]=a[i]]++;
  22. for(int i=1;i<=m;++i)t[i]+=t[i-1];
  23. for(int i=n;i>=1;--i)SA[t[x[i]]--]=i;
  24. for(int k=1;k<=n;k<<=1)
  25. {
  26. int p=0;
  27. for(int i=1;i<=n;++i)y[i]=0;
  28. for(int i=n-k+1;i<=n;++i)y[++p]=i;
  29. for(int i=1;i<=n;++i)if(SA[i]>k)y[++p]=SA[i]-k;
  30. for(int i=0;i<=m;++i)t[i]=0;
  31. for(int i=1;i<=n;++i)t[x[y[i]]]++;
  32. for(int i=1;i<=m;++i)t[i]+=t[i-1];
  33. for(int i=n;i>=1;--i)SA[t[x[y[i]]]--]=y[i];
  34. swap(x,y);
  35. x[SA[1]]=p=1;
  36. for(int i=2;i<=n;++i)x[SA[i]]=cmp(SA[i],SA[i-1],k)?p:++p;
  37. if(p>=n)break;
  38. m=p;
  39. }
  40. for(int i=1;i<=n;++i)rk[SA[i]]=i;
  41. for(int i=1,j=0;i<=n;++i)
  42. {
  43. if(j)--j;
  44. while(a[i+j]==a[SA[rk[i]-1]+j])++j;
  45. hg[rk[i]]=j;
  46. }
  47. }
  48. int Q1[MAX],top1,S1[MAX];
  49. int Q2[MAX],top2,S2[MAX];
  50. ll ans,sum1,sum2;
  51. char ch[MAX];
  52. int main()
  53. {
  54. scanf("%s",ch+1);
  55. for(int i=1,l=strlen(ch+1);i<=l;++i)a[++n]=ch[i]-96,gr[n]=1;
  56. a[++n]=27;
  57. scanf("%s",ch+1);
  58. for(int i=1,l=strlen(ch+1);i<=l;++i)a[++n]=ch[i]-96,gr[n]=2;
  59. GetSA();
  60. for(int i=1,tot=0;i<n;++i)
  61. {
  62. ans+=(gr[SA[i]]==1)?sum2:sum1;
  63. ll tmp1=0;
  64. while(top1&&Q1[top1]>=hg[i+1])
  65. {
  66. tmp1+=S1[top1];
  67. sum1-=1ll*(Q1[top1]-hg[i+1])*S1[top1];
  68. --top1;
  69. }
  70. ++top1;S1[top1]=tmp1;Q1[top1]=hg[i+1];
  71. ll tmp2=0;
  72. while(top2&&Q2[top2]>=hg[i+1])
  73. {
  74. tmp2+=S2[top2];
  75. sum2-=1ll*(Q2[top2]-hg[i+1])*S2[top2];
  76. --top2;
  77. }
  78. ++top2;S2[top2]=tmp2;Q2[top2]=hg[i+1];
  79. if(gr[SA[i]]==1)++S1[top1],sum1+=hg[i+1];
  80. else ++S2[top2],sum2+=hg[i+1];
  81. }
  82. printf("%lld\n",ans);
  83. return 0;
  84. }

【BZOJ4566】找相同字符(后缀数组)的更多相关文章

  1. 【BZOJ4566】[Haoi2016]找相同字符 后缀数组+单调栈

    [BZOJ4566][Haoi2016]找相同字符 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同 ...

  2. [HAOI2016] 找相同字符 - 后缀数组,单调栈

    [HAOI2016] 找相同字符 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. \(n,m \l ...

  3. BZOJ.4566.[HAOI2016]找相同字符(后缀数组 单调栈)

    题目链接 给定两个字符串,求它们有多少个相同子串.相同串的位置不同算多个. POJ3145简化版. 后缀自动机做法见这儿,又快又好写(一下就看出差距了..) //13712kb 4076ms #inc ...

  4. [BZOJ4566][Haoi2016]找相同字符 后缀自动机+dp

    4566: [Haoi2016]找相同字符 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1212  Solved: 694[Submit][Stat ...

  5. BZOJ 4566: [Haoi2016]找相同字符 [后缀自动机]

    4566: [Haoi2016]找相同字符 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 275  Solved: 155[Submit][Statu ...

  6. BZOJ 4566 JZYZOJ 1547 [haoi2016T5]找相同子串 后缀数组 并查集

    http://172.20.6.3/Problem_Show.asp?id=1547 http://www.lydsy.com/JudgeOnline/problem.php?id=4566 单纯后缀 ...

  7. BZOJ4566: [Haoi2016]找相同字符(后缀自动机)

    题意 题目链接 Sol 直接在SAM上乱搞 枚举前缀,用SAM统计可以匹配的后缀,具体在匹配的时候维护和当前节点能匹配的最大值 然后再把parent树上的点的贡献也统计上,这部分可以爆跳parent树 ...

  8. bzoj4566 找相同字符

    题意:给定两个字符串,从中各取一个子串使之相同,有多少种取法.允许本质相同. 解:建立广义后缀自动机,对于每个串,分别统计cnt,之后每个点的cnt乘起来.记得开long long #include ...

  9. HAOI2016 找相同字符 后缀自动机

    两个串,考虑一建一跑.枚举模式串的位置\(i\),考虑每次统计以\(i\)结尾的所有符合要求的串.在后缀自动机上走时记录当前匹配长度\(curlen\),则当前节点的贡献是\((curlen-len[ ...

  10. bzoj4566 / P3181 [HAOI2016]找相同字符

    P3181 [HAOI2016]找相同字符 后缀自动机 (正解应是广义后缀自动机) 并不会广义后缀自动机. 然鹅可以用普通的后缀自动机.   我们先引入一个问题:算出从一个串内取任意两个不重合子串完全 ...

随机推荐

  1. Nginx配置参数中文说明

    #定义Nginx运行的用户和用户组 user www www;   #nginx进程数,建议设置为等于CPU总核心数. worker_processes 8;   #全局错误日志定义类型,[ debu ...

  2. ConcurrenHashMap源码分析(二)

    本篇博客的目录: 一:put方法源码 二:get方法源码 三:rehash的过程 四:总结 一:put方法的源码 首先,我们来看一下segment内部类中put方法的源码,这个方法它是segment片 ...

  3. JavaScript 知识点

    JS基础 页面由三部分组成: html:超文本标记语言,负责页面结构 css:层叠样式表,负责页面样式 js:轻量级的脚本语言,负责页面的动效和数据交互 小总结:结构,样式和行为,三者相分离 在htm ...

  4. Android查缺补漏(IPC篇)-- 款进程通讯之AIDL详解

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8436529.html 进程间通讯篇系列文章目录: Android查缺补漏(IP ...

  5. Sping Boot入门到实战之入门篇(三):Spring Boot属性配置

    该篇为Sping Boot入门到实战系列入门篇的第三篇.介绍Spring Boot的属性配置.   传统的Spring Web应用自定义属性一般是通过添加一个demo.properties配置文件(文 ...

  6. R语言包的安装

    pheatmap包的安装 1: 首先R语言的安装路径里面最好不要有中文路径 2: 在安装其他依存的scales和colorspace包时候要关闭防火墙 错误提示: 试开URL'https://mirr ...

  7. HDU - 3533 bfs [kuangbin带你飞]专题二

    看了好久的样例才看懂. 题意:有一个人要从(0,0)走到(n,m),图中有k个碉堡,每个碉堡可以向某个固定的方向每隔t秒放一次炮,炮弹不能穿越另一个碉堡,会被阻挡.人在移动的过程中不会被炮弹打到,也就 ...

  8. day1(变量、常量、注释、用户输入、数据类型)

    一.变量 name = "SmallNine" 等号前面是变量名(标识符),等号后面是变量值 变量的主要作用:就是把程序运算的中间结果临时存到内存里,已备后面的代码继续调用. 变量 ...

  9. django-装饰器实现PV统计

    1.models层建立统计表 # 每日访问量统计 class Statistics(models.Model): pv = models.IntegerField(default=0) uv = mo ...

  10. a标签文字选中后的颜色样式更改

    ::selection 选择器,选择被用户选取的元素部分.是css3的用法,讲真,我觉得这个东西没必要特地去写.因为选中样式默认的会根据你的背景颜色还有字体color来设置颜色 这是我默认的样式