传送门

后缀自动机基础题。

给两个字符串,让你求长度不小于kkk的公共子串的数量。


这题可以用后缀自动机解决废话

考虑对其中一个字串建出后缀自动机,然后用另一个在上面跑,注意到如果一个状态有贡献的话,从它到根的状态都会有贡献,因此我们给每个节点打一个懒标记最后再统计一次答案即可。

代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define ri register int
  6. using namespace std;
  7. const int N=2e5+5;
  8. typedef long long ll;
  9. int k,n;
  10. char s[N];
  11. inline int calc(char c){return c>='a'&&c<='z'?c-'a':c-'A'+26;}
  12. struct SAM{
  13. int tot,rt,last,len[N],link[N],son[N][60],siz[N],lz[N],cnt[N],rk[N];
  14. inline void init(){
  15. memset(len,0,sizeof(len)),memset(siz,0,sizeof(siz)),memset(rk,0,sizeof(rk)),memset(son,0,sizeof(son));
  16. memset(link,0,sizeof(link)),memset(cnt,0,sizeof(cnt)),memset(lz,0,sizeof(lz)),tot=last=rt=1,len[0]=-1;
  17. }
  18. inline void expend(int x){
  19. int p=last,np=++tot;
  20. siz[last=np]=1,len[np]=len[p]+1;
  21. while(p&&!son[p][x])son[p][x]=np,p=link[p];
  22. if(!p){link[np]=rt;return;}
  23. int q=son[p][x],nq;
  24. if(len[q]==len[p]+1){link[np]=q;return;}
  25. len[nq=++tot]=len[p]+1,memcpy(son[nq],son[q],sizeof(son[q])),link[nq]=link[q];
  26. while(p&&son[p][x]==q)son[p][x]=nq,p=link[p];
  27. link[q]=link[np]=nq;
  28. }
  29. inline void topsort(){
  30. for(ri i=1;i<=tot;++i)++cnt[len[i]];
  31. for(ri i=1;i<=last;++i)cnt[i]+=cnt[i-1];
  32. for(ri i=1;i<=tot;++i)rk[cnt[len[i]]--]=i;
  33. for(ri i=tot;i;--i)siz[link[rk[i]]]+=siz[rk[i]];
  34. }
  35. inline void query(){
  36. topsort();
  37. int p=1,nowlen=0;
  38. ll ans=0;
  39. for(ri i=1;i<=n;++i){
  40. int x=calc(s[i]);
  41. if(son[p][x])p=son[p][x],++nowlen;
  42. else{
  43. while(p&&!son[p][x])p=link[p];
  44. if(!p)p=1,nowlen=0;
  45. else nowlen=len[p]+1,p=son[p][x];
  46. }
  47. if(nowlen>=k){
  48. ans+=(ll)(nowlen-max(k,len[link[p]]+1)+1)*siz[p];
  49. if(len[link[p]]>=k)++lz[link[p]];
  50. }
  51. }
  52. for(ri i=tot;i;--i){
  53. p=rk[i];
  54. ans+=(ll)lz[p]*siz[p]*(len[p]-max(k,len[link[p]]+1)+1);
  55. if(len[link[p]]>=k)lz[link[p]]+=lz[p];
  56. }
  57. cout<<ans<<'\n';
  58. }
  59. }sam;
  60. int main(){
  61. while(scanf("%d",&k),k){
  62. scanf("%s",s+1),n=strlen(s+1),sam.init();
  63. for(ri i=1;i<=n;++i)sam.expend(calc(s[i]));
  64. scanf("%s",s+1),n=strlen(s+1),sam.query();
  65. }
  66. return 0;
  67. }

2018.12.15 poj3415 Common Substrings(后缀自动机)的更多相关文章

  1. 2018.12.15 hdu4641 K-string(后缀自动机)

    传送门 后缀自动机基础题. 题意简述:支持动态在串尾插入字符,查询在串中出现超过kkk次的子串的个数. 动态修改samsamsam,每次增量构造好了之后在parentparentparent树上从新建 ...

  2. POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数

    题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K ...

  3. POJ3415 Common Substrings(后缀数组 单调栈)

    借用罗穗骞论文中的讲解: 计算A 的所有后缀和B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k 的部分全部加起来.先将两个字符串连起来,中间用一个没有出现过的字符隔开.按height ...

  4. poj3415 Common Substrings (后缀数组+单调队列)

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9414   Accepted: 3123 Description A sub ...

  5. 2018.12.22 bzoj3277: 串(后缀自动机+启发式合并)

    传送门 跟这道题是一模一样的. 于是本蒟蒻又写了一遍10min1A庆祝 代码: #include<bits/stdc++.h> #define ri register int using ...

  6. 2018.12.22 bzoj3473: 字符串(后缀自动机+启发式合并)

    传送门 调代码调的我怀疑人生. 启发式合并用迭代写怎么都跑不过(雾 换成了dfsdfsdfs版本的终于过了233. 题意简述:求给出nnn个字串,对于每个给定的字串求出其有多少个字串在至少kkk个剩下 ...

  7. Tencent Cloud Developers Conference(2018.12.15)

    时间:2018.12.15地点:北京朝阳悠唐皇冠假日酒店

  8. 2018.12.15 spoj Substrings(后缀自动机)

    传送门 后缀自动机基础题. 求长度为iii的子串出现次数的最大值. 对原串建出samsamsam,然后用sizsizsiz更新每个maxlenmaxlenmaxlen的答案. 然后由于后缀链接将其转化 ...

  9. 2018.12.15 spoj Longest Common Substring II(后缀自动机)

    传送门 后缀自动机基础题. 给出10个串求最长公共子串. 我们对其中一个建一个samsamsam,然后用剩下九个去更新范围即可. 代码: #include<bits/stdc++.h> # ...

随机推荐

  1. e-olymp Problem9 N-digit numbers(打表)

    传送门:点我 N-digit numbers Find the quantity of N-digit numbers, which the sum is equal to their product ...

  2. 学习Auxre记录

    1.下载地址:https://www.axure.com.cn/3510/(可以免费试用30天) 2.视频教程:https://huke88.com/course/6455.html 3.文字教程:h ...

  3. Linux系统(Centos)下安装nodejs并配置环境

    总结Centos下安装nodejs并配置环境,记录成功安装的方法.推荐的安装方法是利用已编译的二进制文件安装,不推荐使用源码的形式安装,一是源码安装比较麻烦,二是需要自行下载编译浪费时间. 1.安装n ...

  4. mysql垂直分区和水平分区

    数据库扩展大概分为以下几个步骤: 1.读写分离:当数据库访问量还不是很大的时候,我们可以适当增加服务器,数据库主从复制的方式将读写分离: 2.垂直分区:当写入操作一旦增加的时候,那么主从数据库将花更多 ...

  5. Mac git 终端使用

    终端有这个提示,这个按照命令 输入你的 git账号和邮箱就可以, 不然一直出这个提示 Your name and email address were configured automatically ...

  6. 两个App之间的跳转 并传值

    两个App之间的传值最主要的是方法是 Intent intent = getPackageManager().getLaunchIntentForPackage("com.example.a ...

  7. 解决JFinal多文件上传时只获取到第一个文件名

    我的思路: 用户生成时随即生成一串随机字符作为该用户的文件上传目录,并保存该字符串到用户的某一字段.需要显示上传的附件时,遍历这个文件夹.上传时可把文件名设置为上传时间. 1.生成上传路径 可写在注册 ...

  8. <history> 特别报道:Google离职富翁们都在干什么?

    特别报道:Google离职富翁们都在干什么? 时间:2008-01-23 10:16:47作者:CNET科技资讯网 本文关键词:Google CNET科技资讯网1月23日国际报道 假如你拥有1千万或1 ...

  9. js原生语法实现表格操作

    HTML页面: <!doctype html> <html lang="en"> <head> <meta charset="U ...

  10. C# 一段通用的写log 日志的好程序

    public void Write(string text) { FileStream fs = new FileStream(Application.StartupPath+"/log.t ...