原题链接P5341 [TJOI2019]甲苯先生和大中锋的字符串

题目描述

大中锋有一个长度为 n 的字符串,他只知道其中的一个子串是祖上传下来的宝藏的密码。但是由于字符串很长,大中锋很难将这些子串一一尝试。

这天大中锋找到甲苯先生算命,但是甲苯先生说:“天机不可泄漏”。

在大中锋的苦苦哀求下,甲苯先生告诉大中锋:“密码是在字符串中恰好出现了 kk 次的子串”。

但是大中锋不知道该怎么做,在大中锋再三的恳求下,甲苯先生看其真诚,又告诉他:“在恰好出现了 k 次的子串中,你去按照字串的长度分类,密码就在数量最多的那一类里”。

大中锋为了尝试这个密码,想让你帮忙找出子串长度出现次数最多的长度数(如果有多个输出最长长度)。

输入输出格式

输入格式:

第一行一个正整数 T ,表示有 T 组测试数据。

接下来 T 行每行包含一个字符串和一个正整数 k 。


输出格式:

一共输出 T 行,每行一个整数表示在出现 k 次的子串中出现次数的最多的长度。如果不存在子串出现 k 次,则输出 −1 。

输入输出样例

输入样例#1: 复制

  1. 6
  2. aab 1
  3. abc 1
  4. aaaa 2
  5. abab 2
  6. ababacc 2
  7. abab 4
输出样例#1: 复制

  1. 2
  2. 1
  3. 3
  4. 1
  5. 2
  6. -1

说明

数据说明

对于第一个数据:其中子串 b,aa,ab,aab 均只出现一次,其中长度为 1 的子串现了 1 次,长度为 2 的子串出现了 2 次,长度为 3 的子串出现了 1 次。所以答案为 2 。

对于第二个数据:其中子串 a, b, c, ab, bc, abc 均只出现一次,其中长度为 1 的子串出现了 3 次,长度为 2 的子串出现了 2 次,长度为 3 的子串出现了 1 次。所以答案为 1 。

对于第三个数据:其中子串 aaa 出现二次,长度为 3 的子串出现了 1 次,其他长度均没有。所以答案为 3 。

对于第四个数据:其中子串 a, b, ab 出现二次,其中长度为 1 的子串出现了 2 次,长度为 2 的子串出现了 1次。所以答案为 1 。

对于第五个数据:其中子串 b, c, ab, ba 出现二次,其中长度为 1 的子串出现了 2 次,长度为 2 的子串出现了 2次。所以答案为 2 。

对于第六个数据:其中子串没有出现四次。所以本题的本题的答案为 −1 。

数据范围

对于 20% 的数据, 1≤k≤n≤10

对于 100% 的数据, 1≤n≤105,1≤T≤100,∑n≤3∗106 ,输入的字符串中仅包含小写英文字母。

题解

 题意概括:给定一个字符串和整数k,求在其中出现次数为k的子串中数量最多的长度

(如果长度为i的出现为k次的子串有ans个,且任意j<i满足长度为j的出现次数为k的子串数量≤ans,j>i则<ans)

算法:统计子串(数量)问题,很容易想到后缀自动机SAM,后缀数组SA

此处介绍SAM的做法,实现很简单,代码接近于模板

实现:

1.初始化,按照原字符串建立SAM,建立后缀树,递归统计子串数量siz

2.核心代码:统计每一种长度的出现次数为k的子串的数量(“子串的数量”为不同子串的种类数

定义ans数组,ans[i]表示长度为i的出现次数为k的子串的数量,ans[x]max=ans[i]则i即为所求

如何求ans数组?

对于每个状态,如果它的siz(代表的子串的出现次数)为k,则其代表的所有子串为所求,故可按长度统计入ans

那状态i代表的子串的长度又几何?

根据后缀自动机性质,令len[i]为状态i表示的最长的子串str[i]的长度,则

①状态i表示的所有子串为str[i]连续的后缀

②状态i的后缀连接指向的状态link[i]表示的所有子串为str[i]的后缀

③len[link[i]]+1等于i表示的最短的子串的长度

所以状态i对ans的贡献即为对于x|len[link[i]]+1≤x≤len[i],ans[x]++;

故可设ans为前缀和数组,将ans[len[link[i]]+1]++,ans[len[i]+1]--;

以下代码可在递归时操作,亦可另起一个循环

  1. if(x&&siz[x]==K){
  2. ans[len[link[x]]+]++;
  3. ans[len[x]+]--;
  4. }

完整代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. const int INF=1e9+,MAXN=2e5+,MAXC=;
  5. int nxt[MAXN][MAXC],link[MAXN],len[MAXN],lst,sz,siz[MAXN];
  6. inline void extend(int c){
  7. int cur=++sz,p=lst;
  8. len[cur]=len[p]+;
  9. siz[cur]=;
  10. while(p!=-&&!nxt[p][c]){
  11. nxt[p][c]=cur;
  12. p=link[p];
  13. }
  14. if(p==-)
  15. link[cur]=;
  16. else{
  17. int q=nxt[p][c];
  18. if(len[q]==len[p]+)
  19. link[cur]=q;
  20. else{
  21. int clone=++sz;
  22. len[clone]=len[p]+;
  23. memcpy(nxt[clone],nxt[q],sizeof(nxt[clone]));
  24. link[clone]=link[q];
  25. while(p!=-&&nxt[p][c]==q){
  26. nxt[p][c]=clone;
  27. p=link[p];
  28. }
  29. link[q]=link[cur]=clone;
  30. }
  31. }
  32. lst=cur;
  33. }
  34. int tp,head[MAXN],to[MAXN],nxt_[MAXN];
  35. inline void add(int x,int y){
  36. nxt_[++tp]=head[x];
  37. head[x]=tp;
  38. to[tp]=y;
  39. }
  40. int K,ans[MAXN];
  41. void dfs(int x){
  42. for(int i=head[x];i;i=nxt_[i]){
  43. dfs(to[i]);
  44. siz[x]+=siz[to[i]];
  45. }
  46. if(x&&siz[x]==K){
  47. ans[len[link[x]]+]++;
  48. ans[len[x]+]--;
  49. }
  50. }
  51. char str[MAXN];
  52. int M;
  53. int Case;
  54. int main(){
  55. scanf("%d",&Case);
  56. while(Case--){
  57. lst=sz=tp=;
  58. link[]=-;
  59. scanf("%s%d",str+,&K);
  60. M=strlen(str+);
  61. for(int i=;i<=M;i++)
  62. extend(str[i]-'a'),siz[lst]=;
  63. for(int i=;i<=sz;i++)
  64. add(link[i],i);
  65. dfs();
  66. for(int i=;i<=M;i++)
  67. ans[i]+=ans[i-];
  68. int maxi=;
  69. for(int i=M;i>=;i--)
  70. if(ans[i]>ans[maxi])
  71. maxi=i;
  72. printf("%d\n",maxi?maxi:-);
  73. for(int i=;i<=sz;i++){
  74. len[i]=siz[i]=link[i]=;
  75. }
  76. memset(head,,sizeof(head));
  77. memset(ans,,sizeof(ans));
  78. memset(nxt,,sizeof(nxt));
  79. }
  80. return ;
  81. }

洛谷P5341 [TJOI2019]甲苯先生和大中锋的字符串的更多相关文章

  1. 【题解】Luogu P5341 [TJOI2019]甲苯先生和大中锋的字符串

    原题传送门 实际按照题意模拟就行 我们先求出字符串的sa 因为要在字符串中出现k次,所以我们枚举\(l,r(r-l+1=k)\)看一共有多少种合法的方案 合法方案的长度下界\(lb\)为\(Max(h ...

  2. luogu P5341 [TJOI2019]甲苯先生和大中锋的字符串

    传送门 考虑子串以及出现个数,可以发现SAM可以快速知道每种子串的出现次数,即所在状态的\(endpos\)集合大小,然后一个状态对应的子串长度是一段连续区间,所以可以对每个状态差分一下,就能统计答案 ...

  3. p5341 [TJOI2019]甲苯先生和大中锋的字符串

    分析 TJOI白给题 建出sam,对于每个点如果它的子树siz和等于k 那么对于这个满足的点它有贡献的长度一定是一个连续区间 直接差分即可 代码 #include<bits/stdc++.h&g ...

  4. [TJOI2019]甲苯先生和大中锋的字符串——后缀自动机+差分

    题目链接: [TJOI2019]甲苯先生和大中锋的字符串 对原串建后缀自动机并维护$parent$树上每个点的子树大小,显然子树大小为$k$的节点所代表的子串出现过$k$次,那么我们需要将$[len[ ...

  5. 【洛谷 P5341】 [TJOI2019]甲苯先生和大中锋的字符串(后缀自动机)

    题目链接 建出\(sam\),求出parent tree上每个点的\(endpos\)集合大小. 如果等于\(k\),说明到达这个点的都可以.给\((len[fa(i)],len[i]]\)的\(cn ...

  6. Tjoi2019 甲苯先生和大中锋的字符串 后缀自动机_差分

    tjoi胆子好大,直接出了两道送分题...... 都 9102 年了,还有省选出模板题QAQ...... Code: #include <bits/stdc++.h> #define se ...

  7. [TJOI2019]甲苯先生和大中锋的字符串

    有个叫asuldb的神仙来嘲讽我 说这题SAM水题,而且SA过不了 然后我就用SA过了 显然是一个Height数组上长为k的滑块,判一下两边,差分一下就可以了 #include"cstdio ...

  8. 洛谷P5338 [TJOI2019]甲苯先生的滚榜

    原题链接洛谷P5338 [TJOI2019]甲苯先生的滚榜 题目描述 甲苯先生在制作一个online judge,他发现做比赛的人们很关心自己的排名(显而易见),在acm赛制的比赛中,如果通过题目数量 ...

  9. 洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速$dp\&Floyd$)

    洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速\(dp\&Floyd\)) 标签:题解 阅读体验:https://zybuluo.com/Junl ...

随机推荐

  1. eclispe 创建maven 项目:Could not resolve archetype org.apache.maven.archetypes

    昨天新装eclispe 后,创建maven工程后出现 Could not resolve archetype org.apache.maven.archetypes:maven-archetype-q ...

  2. 循环神经网络RNN

    转自 http://blog.csdn.net/xingzhedai/article/details/53144126 更多参考:http://blog.csdn.net/mafeiyu80/arti ...

  3. Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(前言)

    简单介绍一下,本框架的基本功能点: Spring:整个框架的主体部分,这个自不用说. SpringMVC:MVC部分我还是比较喜欢Spring的. MyBatis:选型的时候选择这个ORM主要也是考虑 ...

  4. 使用mapreduce对日志进行清洗

    网站日志分析项目案例(一)项目介绍:http://www.cnblogs.com/edisonchou/p/4449082.html 网站日志分析项目案例(二)数据清洗:当前页面 网站日志分析项目案例 ...

  5. iOS开发系列-常见离线存储方式

    概述 在很多社交App手机在手机没有网络时,重新启动应用,依然能否展示上次访问的数据,提高用户体验,这个就是离线数据存储的运用场景.在iOS开发中常见的离线存储技术有Plist存储.个人偏好存储.解归 ...

  6. PHP算法之Z 字形变换

    将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L C I RE T ...

  7. 本地git安装完成之后,从远程git服务器上面下载代码。报错SSL certificate problem:self signed certificate in certificate chain。

    解决方案:打开git的控制端黑窗口,输入: git config --global http.sslVerify false 点击Entry之后,就会去掉git的ssl验证. 然后就可以正常的下载代码 ...

  8. arc098E Range Minimum Queries

    题意:给你一个n个数的数组,每次能够选取连续的长度为K的子序列,取出其中任意一个最小元素. 一共操作Q次.问取出的元素中Max-Min最小是多少? 标程: #include<bits/stdc+ ...

  9. cocos2D-X 常用功能封装

    Packaging_Kernel.h #pragma once #include <string> #include <map> #include <vector> ...

  10. Eclipse MyBatis generator 1.3.7插件的核心包(中文注释)

    一.最近刚搭建一个项目框架,使用springboot + mybatis,但是在使用Eclipse开发时发现开发mybatis的Dao.mapper.xml和entity时特别不方便,手工去写肯定是不 ...