把两个串中间加一个未出现字符接起来,然后求SA

然后把贡献统计分为两部分,在排序后的后缀里,属于串2的后缀和排在他前面属于串1的后缀的贡献和属于串1的后缀和排在他前面属于串2的后缀的贡献

两部分分别作,都用单调栈维护一段里的height最小值(因为lcp是排序后两后缀中间height最小值),然后根据每次入栈种类来给答案算贡献

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. const int N=500005;
  6. int n,m,k,wa[N],wb[N],wv[N],wsu[N],sa[N],rk[N],he[N],s[N],v[N],top;
  7. long long tot,ans;
  8. char c[N],t[N];
  9. bool cmp(int r[],int a,int b,int l)
  10. {
  11. return r[a]==r[b]&&r[a+l]==r[b+l];
  12. }
  13. void saa(char r[],int n,int m)
  14. {
  15. int *x=wa,*y=wb;
  16. for(int i=0;i<=m;i++)
  17. wsu[i]=0;
  18. for(int i=1;i<=n;i++)
  19. wsu[x[i]=r[i]]++;
  20. for(int i=1;i<=m;i++)
  21. wsu[i]+=wsu[i-1];
  22. for(int i=n;i>=1;i--)
  23. sa[wsu[x[i]]--]=i;
  24. for(int j=1,p=1;j<n&&p<n;j<<=1,m=p)
  25. {
  26. p=0;
  27. for(int i=n-j+1;i<=n;i++)
  28. y[++p]=i;
  29. for(int i=1;i<=n;i++)
  30. if(sa[i]>j)
  31. y[++p]=sa[i]-j;
  32. for(int i=1;i<=n;i++)
  33. wv[i]=x[y[i]];
  34. for(int i=0;i<=m;i++)
  35. wsu[i]=0;
  36. for(int i=1;i<=n;i++)
  37. wsu[wv[i]]++;
  38. for(int i=1;i<=m;i++)
  39. wsu[i]+=wsu[i-1];
  40. for(int i=n;i>=1;i--)
  41. sa[wsu[wv[i]]--]=y[i];
  42. swap(x,y);
  43. p=1;
  44. x[sa[1]]=1;
  45. for(int i=2;i<=n;i++)
  46. x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p:++p;
  47. }
  48. for(int i=1;i<=n;i++)
  49. rk[sa[i]]=i;
  50. for(int i=1,j,k=0;i<=n;he[rk[i++]]=k)
  51. for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
  52. }
  53. int main()
  54. {
  55. while(scanf("%d",&k)&&k)
  56. {
  57. scanf("%s%s",c+1,t+1);
  58. n=strlen(c+1),m=strlen(t+1);
  59. c[n+1]=1;
  60. for(int i=n+2;i<=n+m+1;i++)
  61. c[i]=t[i-n-1];
  62. saa(c,n+m+1,200);
  63. sa[0]=n+m+2;
  64. // for(int i=0;i<=n+m+2;i++)
  65. // cerr<<sa[i]-1<<" ";
  66. // cerr<<endl;
  67. ans=0,top=0,tot=0;
  68. for(int i=1;i<=n+m+1;i++)
  69. {
  70. if(he[i]<k)
  71. top=0,tot=0;
  72. else
  73. {
  74. int con=0;
  75. if(sa[i-1]<=n)
  76. con++,tot+=he[i]-k+1;
  77. while(top>0&&he[i]<=s[top])
  78. tot-=v[top]*(s[top]-he[i]),con+=v[top--];
  79. s[++top]=he[i],v[top]=con;
  80. if(sa[i]>n+1)
  81. ans+=tot;//cerr<<tot<<endl;
  82. }
  83. }//cerr<<ans<<endl;
  84. top=0,tot=0;
  85. for(int i=1;i<=n+m+1;i++)
  86. {
  87. if(he[i]<k)
  88. top=0,tot=0;
  89. else
  90. {
  91. int con=0;
  92. if(sa[i-1]>n+1)
  93. con++,tot+=he[i]-k+1;
  94. while(top>0&&he[i]<=s[top])
  95. tot-=v[top]*(s[top]-he[i]),con+=v[top--];
  96. s[++top]=he[i],v[top]=con;
  97. if(sa[i]<=n)
  98. ans+=tot;
  99. }
  100. }
  101. printf("%lld\n",ans);
  102. }
  103. return 0;
  104. }

poj 3415 Common Substrings【SA+单调栈】的更多相关文章

  1. 【POJ3415】 Common Substrings (SA+单调栈)

    这道是求长度不小于 k 的公共子串的个数...很不幸,我又TLE了... 解法参考论文以及下面的链接 http://www.cnblogs.com/vongang/archive/2012/11/20 ...

  2. POJ 3415 Common Substrings(后缀数组 + 单调栈)题解

    题意: 给两个串\(A.B\),问你长度\(>=k\)的有几对公共子串 思路: 先想一个朴素算法: 把\(B\)接在\(A\)后面,然后去跑后缀数组,得到\(height\)数组,那么直接\(r ...

  3. poj 3415 Common Substrings(后缀数组+单调栈)

    http://poj.org/problem?id=3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K Total Sub ...

  4. poj 3415 Common Substrings - 后缀数组 - 二分答案 - 单调栈

    题目传送门 传送点I 传送点II 题目大意 给定串$A, B$,求$A$和$B$长度大于等于$k$的公共子串的数量. 根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid ...

  5. POJ 3415 Common Substrings(长度不小于K的公共子串的个数+后缀数组+height数组分组思想+单调栈)

    http://poj.org/problem?id=3415 题意:求长度不小于K的公共子串的个数. 思路:好题!!!拉丁字母让我Wa了好久!!单调栈又让我理解了好久!!太弱啊!! 最简单的就是暴力枚 ...

  6. poj 3415 Common Substrings——后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...

  7. poj 3415 Common Substrings —— 后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...

  8. poj 3415 Common Substrings 后缀数组+单调栈

    题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...

  9. POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)

    Description A substring of a string T is defined as: T( i, k)= TiTi+1... Ti+k-1, 1≤ i≤ i+k-1≤| T|. G ...

随机推荐

  1. INAPP

    1. Login API : 接口為您提供了我們的登入服務,可以讓使用者透過facebook帳號登入我們的服務,在您呼叫此API後,可以得到 使用者的UUID(Unique UID為使用者在平台的唯一 ...

  2. ADO.NET EF 4.2 中的查询缓存(避免查询缓存)

    在WinForm系统中遇到了个问题,Form1是查询窗口,根据条件查询出所有数据,双击列表后创建弹出Form2窗口编辑单个记录,但编辑后保存后,在Form2中查询到的还是旧的数据,实际数据库中已经更新 ...

  3. adb的那点小事——360电视助手实现研究

    欢迎转载,转载请注明:http://blog.csdn.net/zhgxhuaa 1.   前言 1.1.  行业背景简单介绍 当下,智能家居与智能穿戴设备无疑是继智能手机后两个最热门的方向.而智能家 ...

  4. linux进程间通信消息队列:msgsnd: Invalid argument

    今天写了个消息队列的小测试程序结果send端程序总是出现:msgsnd: Invalid argument,搞了半个小时也没搞明白,后来查资料发现我将(st_msg_buf.msg_type = 0; ...

  5. (转)使用MAT比较多个heap dump文件

    使用MAT比较多个heap dump文件 调试内存泄露时,有时候适时比较2个或多个heap dump文件是很有用的.这时需要生成多个单独的HPROF文件. 下面是一些关于如何在MAT里比较多个heap ...

  6. C语言的一些特殊使用方法————————【Badboy】

    一:特殊的字符串宏 [cpp] #define A(x) T_##x #define B(x) #@x #define C(x) #x 我们如果x=1, 则上面的宏定义会被解释成下面的样子 A(1)- ...

  7. python第三方库系列之十八--python/django test库

    django是属于python语音的web框架,要说django測试.也能够先说说python的測试.django能够用python的方式測试,当然,django也基于python封装了一个自己的測试 ...

  8. WebService:JAX-WS实现WebService

    WebService和Java核心技术中的RMI一样用于实现异构平台上的应用程序之间数据的交互,唯一不同的是这样的技术屏蔽了语言之间的差异.这也是其大行其道的原因. 实现WebService的技术多种 ...

  9. 【BZOJ】1007 水平可见直线

    [分析] 维护一个下凸包. 首先依照斜率来从小到大排序. 考虑斜率同样的,肯定仅仅能选截距大的,把截距小的给筛掉. 然后用栈来维护下凸包.先压入前两条直线. 然后对于每一条直线i,设栈中上一条直线p= ...

  10. hibernate 的POJO状态

    瞬时状态 刚new出来的对象,还没和session发生联系,或者delete之后的对象 持久化状态 用save,get等方法保存或获取到session中的对象,和数据保持一一对应的关系 脱管状态 对象 ...