link:TJOI2015 弦论

题目大意:

给定一个字符串,输出在对该字符串所有的非空子串排序后第\(k\)个

另外的一个限制是\(T\):子串本质相同但位置不同算\(1\)或多个

\(|s| \leq 5 \times 10^5\)

Solution

“子串排序”,而且数据比较大的时候就要想到后缀自动机了

这个过程有点点像我们在写Treap的时候(就是lyd的书上的代码吧,蒟蒻只学过那一个)

第一步构造一下,套个板子就行

接下来我们先看一下我们的输出代码:

	inline void print(int x,int l)
{
if(l<=val[x]) return ;
l-=val[x];
for(int i=0;i<26;++i)
{
int r=p[x].ch[i]; if(!r) continue;
if(l>sum[r]){l-=sum[r]; continue;}
putchar(i+'a'); print(r,l); return ;
}
}

\(x\)是当前是哪个节点,\(l\)就是还剩下多少的排位

\(val[]\)就是“本质相同串”,有点点类似我们在\(Treap\)上的每一个节点的\(size\)

\(sum[]\)就是子树大小

和\(treap\)找\(rank\)太像了(反正我觉得是)

然后我们的工作就转化成了维护\(sum[]\)的\(val[]\)

看看这段维护代码,一点一点说吧(如果是有学习需要的访客,请跳过这段代码解释,可能有锅)

		for(int i=1;i<=tot;++i) t[len(i)]++;
for(int i=1;i<=tot;++i) t[i]+=t[i-1];
for(int i=1;i<=tot;++i) a[t[len(i)]--]=i;
//上文都是自动机上的操作
//下文就是大力统计“和”
for(int i=tot;i>=1;--i) val[fa(a[i])]+=val[a[i]];
for(int i=1;i<=tot;++i) cas==0?(sum[i]=val[i]=1):(sum[i]=val[i]);
val[1]=sum[1]=0;
for(int i=tot;i>=1;--i)
{
for(int j=0;j<26;++j)
{
if(p[a[i]].ch[j]) sum[a[i]]+=sum[p[a[i]].ch[j]];
}
}

其实到这里我认为是可理解的(博主理解了)

CODE

#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1;char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=2e6+10;
char s[N];
struct node{
int fa,len,ch[26];
#define fa(x) p[x].fa
#define len(x) p[x].len
}p[N];
int t[N],a[N],sum[N],k,las=1,tot=1,len,cas,val[N];
inline void addp(int x)
{
int tmp=las,np=las=++tot; val[tot]=1; p[np].len=p[tmp].len+1;
for(;tmp&&!p[tmp].ch[x];tmp=p[tmp].fa) p[tmp].ch[x]=np;
if(!tmp) p[np].fa=1;
else
{
int q=p[tmp].ch[x];
if(p[q].len==p[tmp].len+1) p[np].fa=q;
else
{
int nq=++tot;
p[nq]=p[q]; p[nq].len=p[tmp].len+1;
p[q].fa=p[np].fa=nq;
for(;tmp&&p[tmp].ch[x]==q;tmp=p[tmp].fa) p[tmp].ch[x]=nq;
}
} return ;
}
inline void print(int x,int l)
{
if(l<=val[x]) return ;
l-=val[x];
for(int i=0;i<26;++i)
{
int r=p[x].ch[i]; if(!r) continue;
if(l>sum[r]){l-=sum[r]; continue;}
putchar(i+'a'); print(r,l); return ;
}
}
signed main()
{
scanf("%s",s+1); cas=read(); k=read(); len=strlen(s+1);
for(int i=1;i<=len;++i) addp(s[i]-'a');
for(int i=1;i<=tot;++i) t[len(i)]++;
for(int i=1;i<=tot;++i) t[i]+=t[i-1];
for(int i=1;i<=tot;++i) a[t[len(i)]--]=i;
for(int i=tot;i>=1;--i) val[fa(a[i])]+=val[a[i]];
for(int i=1;i<=tot;++i) cas==0?(sum[i]=val[i]=1):(sum[i]=val[i]);
val[1]=sum[1]=0;
for(int i=tot;i>=1;--i)
{
for(int j=0;j<26;++j)
{
if(p[a[i]].ch[j]) sum[a[i]]+=sum[p[a[i]].ch[j]];
}
}
if(sum[1]<k) puts("-1");
else print(1,k),puts("");
return 0;
}
}signed main(){return yspm::main();}

LGOJ3975 TJOI2015 弦论的更多相关文章

  1. BZOJ 3998: [TJOI2015]弦论 [后缀自动机 DP]

    3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2152  Solved: 716[Submit][Status] ...

  2. Luogu P3975 [TJOI2015]弦论

    题目链接 \(Click\) \(Here\) 题目大意: 重复子串不算的第\(k\)大子串 重复子串计入的第\(k\)大子串 写法:后缀自动机. 和\(OI\) \(Wiki\)上介绍的写法不太一样 ...

  3. 洛谷 P3975 [TJOI2015]弦论 解题报告

    P3975 [TJOI2015]弦论 题目描述 为了提高智商,ZJY开始学习弦论.这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为\(n\)的字符串,求 ...

  4. 【BZOJ 3998】 3998: [TJOI2015]弦论 (SAM )

    3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2627  Solved: 881 Description 对于一 ...

  5. 【BZOJ3998】[TJOI2015]弦论 后缀自动机

    [BZOJ3998][TJOI2015]弦论 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T ...

  6. BZOJ_3998_[TJOI2015]弦论_后缀自动机

    BZOJ_3998_[TJOI2015]弦论_后缀自动机 Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行 ...

  7. bzoj3998: [TJOI2015]弦论(SAM+dfs)

    3998: [TJOI2015]弦论 题目:传送门 题解: SAM的入门题目(很好的复习了SAM并加强Right集合的使用) 其实对于第K小的字符串直接从root开始一通DFS就好,因为son边是直接 ...

  8. luogu P3975 [TJOI2015]弦论 SAM

    luogu P3975 [TJOI2015]弦论 链接 bzoj 思路 建出sam. 子串算多个的,统计preant tree的子树大小,否则就是大小为1 然后再统计sam的节点能走到多少串. 然后就 ...

  9. 题解-TJOI2015 弦论

    TJOI2015 弦论 字符串 \(s\) 和 \(t\) 和 \(k\).如果 \(t=0\),不同位置的相同子串算 \(1\) 个:如果 \(t=1\),不同位置的相同子串算多个.求 \(k\) ...

随机推荐

  1. map/vector遍历删除

    map遍历删除 map<int, vector<int>>::iterator it = g_map.begin(); for (; it != g_map.end(); /* ...

  2. 79.常用的返回QuerySet对象的方法使用详解: filter, exclude,annotate

    返回新的QuerySet的常用方法: 1.filter: 将满足条件的数据提取出来,返回一个新的QuerySet 以下所使用的模型article,category,定义模型models.py文件中,示 ...

  3. Cracking Digital VLSI Verification Interview 第一章

    目录 Digital Logic Design Number Systems, Arithmetic and Codes Basic Gates Combinational Logic Circuit ...

  4. 使用Map,统计字符串中每个字符出现的次数

    package seday13; import java.util.HashMap; import java.util.Map; /** * @author xingsir * 统计字符串中每个字符出 ...

  5. DevOps专题 |监控,可观测性与数据存储

    对于DevOps而言,监控是其中重要的一环,上一次的专题内容中,我们与大家分享了大型企业级监控系统的设计.今天我们将和大家从另一个角度进一步探讨互联网工程技术领域的监控设计(monitoring):系 ...

  6. 吴裕雄--天生自然MySQL学习笔记:MySQL UNION 操作符

    MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中.多个 SELECT 语句会删除重复的数据. 语法 MySQL UNION 操作符语法格式: SELECT ...

  7. python版本,执行

    01. 第一个 HelloPython 程序 1.1 Python 源程序的基本概念 Python 源程序就是一个特殊格式的文本文件,可以使用任意文本编辑软件做 Python 的开发 Python 程 ...

  8. NodeJS框架一览

    NodeJS 框架一览 Express 当你使用Node.js构建web应用程序时, Express通常被视为事实上的Web服务器.它的哲学(一个可以使用中间件包扩展的简约核心)是大多数Node.js ...

  9. ServiceComb 集成 Shiro 实践|火影专场发布

    Shiro简介 Apache Shiro是一款功能强大.易用的轻量级开源Java安全框架,它主要提供认证.鉴权.加密和会话管理等功能.Spring Security可能是业界用的最广泛的安全框架,但是 ...

  10. 第04项目:淘淘商城(SpringMVC+Spring+Mybatis) 的学习实践总结【第一天】

    本人做过一年的MATLAB编程和简单维护过VB和C++的项目.是跟着网上获得的黑马的Java双元视频课来自学入门Java知识和常用框架的使用. 淘淘商城(SpringMVC+Spring+Mybati ...