其实这道题跟[AHOI2013]差异很像

其实这个问题的本质就是让你算所有后缀的\(lcp\)长度之和,但是得来自两个不同的字符串

先把两个字符串拼起来做一遍\(SA\),由于我们多算了来自于同一个串内的情况

于是在分别对这两个串建\(SA\),减掉这两次算出来的答案

现在的问题转化为求出\(height\)数组所有子区间的最小值的和

我们可以考虑一个动态往序列末尾加数的过程

也就是我们往末尾加一个数都会和之前所有的数形成一个新的区间

考虑快速算出这些区间的最小值的和

我们可以对每一个数存储一个\(a_i\),表示\(i\)到当前序列末尾的最小值是多少

我们每次加入一个数可以对更新一下所有的\(a_i\),把所有比当前加入的数大的\(a_i\)变成当前数就好了

这不就\(T\)了吗

我们发现我们只需要求出所有\(a_i\)的和,并不需要关心这个\(i\)来自哪里,于是我们可以把相等的\(a_i\)放在一起计算,也就是每次新加入一个数就暴力扫一遍把那些比当前加入数大的合并到一个\(a_i\)里

看起来复杂度并不科学,但是最坏情况下就相当于是一个线段树的复杂度了,\(O(n)\)的,跑的还挺快的

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<algorithm>
  5. #define re register
  6. #define LL long long
  7. #define maxn 400005
  8. #define max(a,b) ((a)>(b)?(a):(b))
  9. #define min(a,b) ((a)<(b)?(a):(b))
  10. int het[maxn],sa[maxn],rk[maxn],tp[maxn],tax[maxn];
  11. char S[maxn],T[maxn];
  12. int L1,L2,n,m;
  13. LL a[maxn],cnt[maxn],top;
  14. LL tot;
  15. inline void qsort()
  16. {
  17. for(re int i=0;i<=m;i++) tax[i]=0;
  18. for(re int i=1;i<=n;i++) tax[rk[i]]++;
  19. for(re int i=1;i<=m;i++) tax[i]+=tax[i-1];
  20. for(re int i=n;i;--i) sa[tax[rk[tp[i]]]--]=tp[i];
  21. }
  22. inline LL SA()
  23. {
  24. LL ans=0,sum=0;
  25. memset(rk,0,sizeof(rk)),memset(sa,0,sizeof(sa)),memset(het,0,sizeof(het)),memset(tp,0,sizeof(tp));
  26. memset(a,0,sizeof(a)),memset(cnt,0,sizeof(cnt)),top=0;
  27. m=2500;
  28. for(re int i=1;i<=n;i++) rk[i]=S[i],tp[i]=i;
  29. qsort();
  30. for(re int w=1,p=0;p<n;m=p,w<<=1)
  31. {
  32. p=0;
  33. for(re int i=1;i<=w;i++) tp[++p]=n-w+i;
  34. for(re int i=1;i<=n;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
  35. qsort();
  36. for(re int i=1;i<=n;i++) std::swap(tp[i],rk[i]);
  37. rk[sa[1]]=p=1;
  38. for(re int i=2;i<=n;i++) rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
  39. }
  40. int k=0;
  41. for(re int i=1;i<=n;i++)
  42. {
  43. if(k) --k;
  44. int j=sa[rk[i]-1];
  45. while(S[i+k]==S[j+k]) ++k;
  46. het[rk[i]]=k;
  47. }
  48. for(re int i=2;i<=n;i++)
  49. {
  50. LL now=1;
  51. while(top&&het[i]<=a[top])
  52. now+=cnt[top],sum-=a[top]*cnt[top],top--;
  53. cnt[++top]=now;
  54. a[top]=het[i];
  55. sum+=cnt[top]*a[top];
  56. ans+=sum;
  57. }
  58. return ans;
  59. }
  60. int main()
  61. {
  62. scanf("%s",S+1);scanf("%s",T+1);
  63. L1=strlen(S+1),L2=strlen(T+1);n=L1+L2+1;
  64. S[L1+1]='z'+1;
  65. for(re int i=1;i<=L2;i++) S[i+L1+1]=T[i];
  66. tot+=SA();
  67. for(re int i=L1+1;i<=n;i++) S[i]=0;
  68. n=L1;tot-=SA();
  69. for(re int i=1;i<=L2;i++) S[i]=T[i];
  70. for(re int i=L2+1;i<=n;i++) S[i]=0;
  71. n=L2;
  72. tot-=SA();
  73. printf("%lld\n",tot);
  74. return 0;
  75. }

【[HAOI2016]找相同字符】的更多相关文章

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

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

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

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

  3. 【BZOJ4566】[HAOI2016]找相同字符

    [BZOJ4566][HAOI2016]找相同字符 题面 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. 其中\(1\le ...

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

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

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

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

  6. bzoj 4566 [Haoi2016]找相同字符SA

    4566: [Haoi2016]找相同字符 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 128  Solved: 75[Submit][Status ...

  7. [Bzoj4566][Haoi2016]找相同字符(广义后缀自动机)

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

  8. BZOJ_4566_[Haoi2016]找相同字符_后缀自动机

    BZOJ_4566_[Haoi2016]找相同字符_后缀自动机 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有 ...

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

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

  10. BZOJ4566 [Haoi2016]找相同字符【SAM】

    BZOJ4566 [Haoi2016]找相同字符 给定两个字符串\(s和t\),要求找出两个字符串中所有可以相互匹配的子串对的数量 首先考虑可以怎么做,我们可以枚举\(t\)串的前缀\(t'\),然后 ...

随机推荐

  1. Java 写入pdf文件

    import java.awt.Color; import java.io.File; import java.io.FileOutputStream; import com.lowagie.text ...

  2. 自动化交互expect

    自动化交互expect 一,介绍 每次服务器控制链接都需要输入密码,很麻烦,每次交互大大延长了时间 因此就有了免交互及自动化交互存在expect 二,安装 yum install expect -y ...

  3. 求入栈顺序为1234……N的序列的所有可能的出栈序列

    class Program { private static void Fun(int x, int n, Stack<int> stack, List<int> outLis ...

  4. Unity3D 发布成PC端常用设置

    本文,基于Unity 5.6pro版本来发布PC端.文中若有不妥之处,欢迎各位指出! 一.如何去掉Unity官方水印? 首先,你需要pro版本的Unity3D.如果,你是personal版本的话,就需 ...

  5. Nginx使用的php-fpm的两种进程管理方式及优化

    PS:前段时间配置php-fpm的时候,无意中发现原来它还有两种进程管理方式.与Apache类似,它的进程数也是可以根据设置分为动态和静态的. php-fpm目前主要又两个分支,分别对应于php-5. ...

  6. hash扩展攻击本地实验

    记录一下自己对hash扩展攻击的一些理解,hash扩展攻击主要应用于身份认证,比如对于成功登录的用户可以赋予其一个采用hsah算法加密的cookie值,其中含有未知的密钥. 此后每次在服务器端验证此c ...

  7. C++程序设计基础(4)宏定义和内联

    1.知识点 1.1宏定义 (1)不带参数的宏定义 #define ERROR_MESSAGE -100 #define SECONDS_PER_DAY 60*60*60 (2)带参数宏定义,这种形式称 ...

  8. Visual Studio 安装OpenCV及问题总结

    1.VS安装OpenCV基本步骤 1)安装Visual Studio 下载网址https://opencv.org/releases.html# 2)安装OpenCV 下载网址https://www. ...

  9. oracle 报错:ORA-02019 未找到数据库的连接说明

    一.问题描述 我之前连的是别的数据库,现在更换了数据库的连接,然后就报了如下的错误: 我使用的是NHibernate,我找到映射文件后发现我用了dblink,代码中table="COM_OR ...

  10. nginx安装及优化

    1.pcre及nginx安装包下载 wget http://www.pcre.org/   pcre用yum安装即可 http://nginx.org/en/download.html 2.安装 -安 ...