原题:2018 ICPC Asia-East Continent Final J

想看原题解的可以去看吉老师的直播题解

题意:

题解:

(dllca膜你赛搬原题差评)

考虑题目中给出的式子的含义,实际上相当于要给串$s$的每个后缀分配一个概率$p_i$满足$\sum\limits_{i=1}^{n}p_i=1$,然后取其中一个与其它后缀的lcp期望值最小的后缀,要做的就是求出一种最优的分配p的方案使得最后的最小值最大;

先不考虑后缀,考虑若干个lcp为0(即没有公共前缀)的字符串如何分配最优:

设有$m$个串$s_1,s_2,...,s_m$,长度分别为$l_1,l_2,...,l_m$,那么取其中一个串$s_t$对答案的贡献是$p_tl_t$,最后的答案就是$min\{p_tl_t\}$;

一个结论:要使答案最大,所有$p_tl_t$的值必定相等;

如果不全相等,答案就是其中最小的那个,则必然可以通过调整$p$使得最小的那个增加一点,其他的全部减小一点,从而使答案更优;

于是可以列出一个方程组:

$$\begin{cases}\sum\limits_{i=1}^{n}p_i=1 \\ p_1l_1=p_2l_2=\cdots=p_nl_n=k\end{cases}$$

其中$k$就是答案,联立两式得:

$$k=\frac{1}{\frac{1}{l_1}+\frac{1}{l_2}+\cdots+\frac{1}{l_n}}$$

显然就可以直接求出$k$了;

回到原问题,涉及到快速求后缀的lcp容易想到先构造出后缀树,由于后缀树本质上还是一棵trie树,因此一个节点所有的后继节点以及向下的子树所表示的字符串在这个点向后的部分都是没有公共前缀的,所以可以用上面的方法来处理;

注意到其实某一个节点子树中的问题是整个后缀树上问题完全等价的子问题,因此可以在后缀树上dfs,父节点直接加上子树的答案继续合并即可;

dfs的时候注意如果一个节点本身已经是原串某一个后缀的尾节点那么它的后继节点肯定没有贡献,直接返回0即可;

于是就做完了,讲了这么多代码还是很短的!

代码:

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define inf 2147483647
#define eps 1e-9
using namespace std;
typedef long long ll;
typedef double db;
struct edge{
int v,next;
}a[];
int t,n,tot,last,rt,tote,head[],son[][],mx[],fa[],isp[];
char s[];
void add(int u,int v){
a[++tote].v=v;
a[tote].next=head[u];
head[u]=tote;
}
void extend(int ch){
int p=last,np=++tot;
mx[np]=mx[p]+;
for(;p&&!son[p][ch];p=fa[p])son[p][ch]=np;
if(!p)fa[np]=rt;
else{
int q=son[p][ch];
if(mx[q]==mx[p]+)fa[np]=q;
else{
int nq=++tot;
mx[nq]=mx[p]+;
memcpy(son[nq],son[q],sizeof(son[q]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
for(;p&&son[p][ch]==q;p=fa[p])son[p][ch]=nq;
}
}
isp[np]=true;
last=np;
}
db dfs(int u){
if(isp[u])return ;
db ret=;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
ret+=1.0/(dfs(v)+mx[v]-mx[u]);
}
return 1.0/ret;
}
int main(){
memset(head,-,sizeof(head));
scanf("%d",&t);
while(t--){
scanf("%s",s);
n=strlen(s);
rt=last=++tot;
for(int i=n-;i>=;i--){
extend(s[i]-'a');
}
for(int i=rt+;i<=tot;i++){
add(fa[i],i);
}
printf("%.10lf\n",dfs(rt));
}
return ;
}

【XSY3347】串后缀的更多相关文章

  1. BZOJ 2946: [Poi2000]公共串( 后缀自动机 )

    一个串建后缀自动机, 其他串在上面跑, 然后用当前串跑的去更新全部 ------------------------------------------------------------------ ...

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

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

  3. [BZOJ3230] 相似字串 后缀数组+RMQ

    3230: 相似子串 Time Limit: 20 Sec  Memory Limit: 128 MB Description Input 输入第1行,包含3个整数N,Q.Q代表询问组数.第2行是字符 ...

  4. 【BZOJ2946】[Poi2000]公共串 后缀数组+二分

    [BZOJ2946][Poi2000]公共串 Description        给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l        读入单词 l        计 ...

  5. bzoj 2946 [Poi2000]公共串——后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2946 对每个串都建一个后缀自动机,然后 dfs 其中一个自动机,记录同步的话在别的自动机上走 ...

  6. BZOJ 2946 POI2000 公共串 后缀自动机(多串最长公共子串)

    题意概述:给出N个字符串,每个串的长度<=2000(雾...可能是当年的年代太久远机子太差了),问这N个字符串的最长公共子串长度为多少.(N<=5) 抛开数据结构,先想想朴素做法. 设计一 ...

  7. 【bzoj2946】[Poi2000]公共串 后缀自动机

    [Poi2000]公共串 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1386  Solved: 620[Submit][Status][Discus ...

  8. BZOJ 2946 [Poi2000]公共串 ——后缀自动机

    任意选择一个串作为模式串,构建出后缀自动机. 然后用其他的串在后缀自动机上跑匹配. 然后就到了理解后缀自动机性质的时候. 在某一个节点的最大值是可以沿着parent树上传的. 然后用dp[i][j]表 ...

  9. [BZOJ3277/BZOJ3473] 串 - 后缀数组,二分,双指针,ST表,均摊分析

    [BZOJ3277] 串 Description 现在给定你n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串(注意包括本身). Solution 首先将所有串连 ...

随机推荐

  1. (9)使用JdbcTemplate【从零开始学Spring Boot】

    整体步骤: (1)   在pom.xml加入jdbcTemplate的依赖: (2)   编写DemoDao类,声明为:@Repository,引入JdbcTemplate (3)   编写DemoS ...

  2. ASP.NET--IIS的Http请求流程

    下面的文章是基于IIS经典模式给出的流程图,和IIS集成模式有些区别,WIN7系统自带的是IIS7,和文章分写的有些区别,现在基本上都用IIS7了,所以不要入坑 伯乐在线的文章一 伯乐在线的文章二

  3. [bzoj4084][Sdoi2015]双旋转字符串_hash

    双旋转字符串 bzoj-4084 Sdoi-2015 题目大意:给定两个字符串集合 S 和 T .其中 S 中的所有字符串长度都恰好为 N ,而 T 中所有字符串长度都恰好为 M .且 N+M 恰好为 ...

  4. POJ 1987

    T_T为毛会这样子,我的写就是过不了,....... 其实这题不难,很容易想到吧,我一开始也想着用枚举这类方法,但复杂度实在不敢想,没想到,真的是用这种方法.. 今天学了一个叫树的重心,可以使分治的子 ...

  5. sikuli+eclipse实例

    设置sikuli环境变量 如果在执行脚本的时候出现以下错误: Getting the VisionProxy.dll: Can not find dependent libraries... 把Sik ...

  6. Github 协同开发

    ithub开发流程 Github的流程.也就是: 开发者各自fork项目的repo到自己Github账户下 每次开发同步到项目的repo然后再进行开发 push自己的开发分支到自己Github账户下面 ...

  7. C# Log4Net简单使用方法

    log4net库是Apache log4j框架在Microsoft .NET平台的实现,是一个帮助程序员将日志信息输出到各种目标(控制台.文件.数据库等)的工具. 使用log4net,一个很明显的好处 ...

  8. 深入了解Token认证的来龙去脉

    Token 是在服务端产生的,如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端.前端可以在每次请求的时候带上 Token 证明自己的合法地位.   不久 ...

  9. IOS-UITextField-改变光标颜色

    方法1: [[UITextField appearance] setTintColor:[UIColor blackColor]]; 这种方法将影响所有TextField. 方法2: textFiel ...

  10. html5和css3的笔记

    h5+c3 W3C盒子模型和ie盒子模型 文档<!DOCTYPE html>加上的话,所有浏览器都按照W3C的盒子模型,否则ie会按照ie的盒子模型,它的content包括了padding ...