BZOJ3473&&BZOJ3277串

题面

自己找去

HINT

对于所有串建立一个广义后缀自动机,对于每一个节点开一个set表示这个节点接受的子串在哪些串里出现过,然后在parent tree上做启发式合并,理论复杂度应该是\(nlog_{n}^2\)。

广义后缀自动机

这个广义后缀自动机在建立的时候和后缀自动机时是基本差不多的,就是在每加入一个新串的时候,把\(last=root\)就好了

如何找匹配大等于k次

首先因为每个节点的fa表示的子串都是现在这个节点的后缀,所以fa出现的次数一定\(>=\)当前节点出现的次数(这个东西可以感性认知进行证明),另外,如果一个子串出现次数小等于k,在这个子串后面加一个字符后它的出现次数也不可能大于k次

一句话题解

建立一个广义后缀自动机,然后在每个节点上开个set记录在几个串上出现,然后parent tree上启发式合并set,查询答案的时候不断往父亲节点跳,直到满足条件,然后\(\sum{node[u].len}\)

  1. #include<bits/stdc++.h>
  2. #include<set>
  3. using namespace std;
  4. const int maxn=200010;
  5. inline int read(){
  6. int w=0,f=1;
  7. char ch=getchar();
  8. while(ch<'0'||ch>'9'){
  9. if(ch=='-') f=-1;
  10. ch=getchar();
  11. }
  12. while(ch>='0'&&ch<='9'){
  13. w=(w<<3)+(w<<1)+ch-48;
  14. ch=getchar();
  15. }
  16. return w*f;
  17. }
  18. int n,m;
  19. bool debug;
  20. set<int> s[maxn];
  21. set<int>::iterator it;
  22. struct SUFFIXAUTOMATON{
  23. struct Node{
  24. int len,fa;
  25. map<int,int> ch;
  26. }node[2000010];
  27. int lst,root,tot;
  28. inline void init(){
  29. lst=root=tot=1;return;
  30. }
  31. inline void extend(int now,int id){
  32. int p=lst;tot++;lst=tot;int np=tot;
  33. node[np].len=node[p].len+1;s[np].insert(id);
  34. while(p&&!node[p].ch[now]){
  35. node[p].ch[now]=np;
  36. p=node[p].fa;
  37. }
  38. if(!p) node[np].fa=1;
  39. else{
  40. int q=node[p].ch[now];
  41. if(node[q].len==node[p].len+1){
  42. node[np].fa=q;
  43. }
  44. else{
  45. int nq=++tot;node[nq]=node[q];
  46. node[nq].len=node[p].len+1;
  47. node[q].fa=nq;node[np].fa=nq;
  48. while(p&&node[p].ch[now]==q){
  49. node[p].ch[now]=nq;
  50. p=node[p].fa;
  51. }
  52. }
  53. }
  54. }
  55. }SAM;
  56. string ch[maxn];
  57. int sum[maxn];
  58. struct Edge{
  59. int from,to,next;
  60. }edge[maxn*6];
  61. int cnt,head[maxn];
  62. inline void addedge(int u,int v){
  63. cnt++;
  64. edge[cnt].from=u;
  65. edge[cnt].to=v;
  66. edge[cnt].next=head[u];
  67. head[u]=cnt;
  68. }
  69. inline void dfs(int u){
  70. for(int i=head[u];i;i=edge[i].next){
  71. int v=edge[i].to;dfs(v);
  72. if(s[u].size()<s[v].size()) swap(s[u],s[v]);
  73. for(it=s[v].begin();it!=s[v].end();it++){
  74. s[u].insert(*it);
  75. }
  76. }
  77. sum[u]=s[u].size();
  78. return;
  79. }
  80. int main(){
  81. n=read();m=read();SAM.init();
  82. for(int i=1;i<=n;i++){
  83. cin>>ch[i];int len=ch[i].length();
  84. for(int j=0;j<len;j++){
  85. SAM.extend(ch[i][j]-'a'+1,i);
  86. }
  87. SAM.lst=1;
  88. }
  89. for(int i=1;i<=SAM.tot;i++){
  90. if(SAM.node[i].fa) addedge(SAM.node[i].fa,i);
  91. }
  92. dfs(SAM.root);
  93. if(m>n){
  94. for(int i=1;i<=n;i++){
  95. printf("0 ");
  96. }
  97. return 0;
  98. }
  99. for(int i=1;i<=n;i++){
  100. long long ans=0;int u=SAM.root;int len=ch[i].length();
  101. for(int j=0;j<len;j++){
  102. u=SAM.node[u].ch[ch[i][j]-'a'+1];
  103. while(sum[u]<m) u=SAM.node[u].fa;
  104. ans+=SAM.node[u].len;
  105. }
  106. printf("%lld ",ans);
  107. }
  108. return 0;
  109. }

你以为这就完了吗,naive

我在写最后那个统计答案的时候,想的做法长这样

  1. for(int i=1;i<=n;i++){
  2. long long ans=0;int u=SAM.root;int len=ch[i].length();
  3. for(int j=0;j<len;j++){
  4. u=SAM.node[u].ch[ch[i][j]-'a'+1];int p=u;
  5. while(sum[p]<m) p=SAM.node[p].fa;
  6. ans+=SAM.node[p].len;
  7. }
  8. printf("%lld ",ans);
  9. }

我是想每次匹配完向上跳,但是在bzoj上它TLE了,然后我想了一个妙妙做法,并查集优化

  1. inline int find(int x){
  2. if(sum[x]>=m) return x;
  3. else return f[x]=find(f[x]);
  4. }

然后跑得飞快,就过了

BZOJ3473&&BZOJ3277串的更多相关文章

  1. [BZOJ3473][BZOJ3277]字符串

    [BZOJ3473][BZOJ3277]字符串 试题描述 给定 \(n\) 个字符串,询问每个字符串有多少子串(不包括空串)是所有 \(n\) 个字符串中至少 \(k\) 个字符串的子串? 输入 第一 ...

  2. bzoj3473: 字符串 && bzoj3277串

    3473: 字符串 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 121  Solved: 53[Submit][Status][Discuss] D ...

  3. bzoj3473字符串&bzoj3277串

    题意:给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串.注意本质相同的子串多次出现算多次,如1 1 aaa这组数据答案为6,贡献1WA.代码里有些部分是为了 ...

  4. 【bzoj3277/bzoj3473】串/字符串 广义后缀自动机

    题目描述 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). 输入 第一行两个整数n,k.接下来n行每行一个 ...

  5. BZOJ3277 串 和 BZOJ3473 字符串

    字符串 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? 分析 参照自为风月马前卒和Candy?的题解. 广义后缀自动机不就是把很多串的SAM建到了一个S ...

  6. BZOJ3277 串(后缀数组+二分答案+主席树)

    因为不会SAM,考虑SA.将所有串连起来并加分隔符,每次考虑计算以某个位置开始的子串有多少个合法. 对此首先二分答案,找到名次数组上的一个区间,那么只需要统计有多少个所给串在该区间内出现就可以了.这是 ...

  7. BZOJ3277——串

    0.题意:给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). 1.分析:这个题我问了吴大爷做法 首先建立后缀自动机,然后利用离线搞出每一个 ...

  8. bzoj3277 串 (后缀数组+二分答案+ST表)

    常见操作:先把所有串都连到一起,但中间加上一个特殊的符号(不能在原串中/出现过)作为分割 由于全部的子串就等于所有后缀的所有前缀,那我们对于每一个后缀,去求一个最长的前缀,来满足这个前缀在至少K个原串 ...

  9. 【文文殿下】[BZOJ3277] 串

    Description 字符串是oi界常考的问题.现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中 至少k个字符串的子串(注意包括本身) Input 第一行两个整数n,k ...

随机推荐

  1. MongoDB入门(介绍、安装)

    一.什么是MongoDB? MongoDB is a document database with the scalability and flexibility that you want with ...

  2. Enum, Generic and Templates

    文 Akisann@CNblogs / zhaihj@Github 本篇文章同时发布在Github上:https://zhaihj.github.io/enum-generic-and-templat ...

  3. SpringBoot图文教程5—SpringBoot 中使用Aop

    有天上飞的概念,就要有落地的实现 概念+代码实现是本文的特点,教程将涵盖完整的图文教程,代码案例 文章结尾配套自测面试题,学完技术自我测试更扎实 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例 ...

  4. tomcat solr服务无法搜索中文

    把tomcat的配置文件修改一下就好了, vi server.xml <Connector port="8080" protocol="HTTP/1.1" ...

  5. ubuntu python及python IDLE 的安装

    ubuntu下Python的安装和使用 文章参考出处:https://www.cnblogs.com/luckyalan/p/6703590.html ubuntu14.04 安装Python2.7: ...

  6. U盘制作macOS Sierra的启动盘

    1.macOS Sierra的几种安装方式 *开机时按住command+option+r 进行联网在线安装.PS:在网速好的情况还行,但是如果网络差的时候,它会让你崩溃的. *使用光盘进行安装. *今 ...

  7. Linux系统WEB服务之Nginx基础入门

    一.Nginxi简介 Nginx是什么?它是一个开源.高性能的WEB服务器软件和代理服务器软件,由俄罗斯人Igor Sysoev 开发实现.它的功能主要分三类,第一是它作为一个WEB服务软件使用:第二 ...

  8. python网络爬虫(二)requests库的基本介绍和使用

    一.requests库的七个重要方法 (1)最常用方法:requests.get(url,params=None,**kwargs)//对应HTTP协议的GET()操作 (请求获得URL位置的资源) ...

  9. 手把手教你快速使用数据可视化BI软件创建互联网用户数据分析大屏

    灯果数据可视化BI软件是新一代人工智能数据可视化大屏软件,内置丰富的大屏模板,可视化编辑操作,无需任何经验就可以创建属于你自己的大屏.大家可以在他们的官网下载软件.   本文以互联网用户数据分析大屏为 ...

  10. python实现自动点赞

    1.思路通过pyautogui可以实现鼠标点击.滚动鼠标.截屏等操作.由此功能实现打开页面,进行点赞.aircv可以从大图像获得小图像的位置,利用pyautogui截屏得到的图片,可以在页面获取到每一 ...