\(\mathscr{Description}\)

  Private link.

  令 \(\Sigma=\{\texttt a,\texttt b\}\),对于所有形式语言 \(L\subseteq\Sigma^n\),\(L\) 的最小 DFA 状态数的最大值,以及取到这一最大值时,\(|L|\) 的最小值和最大值。

  \(n\le10^3\)。

\(\mathscr{Solution}\)

  引理 对于任意串 \(x,y\in\Sigma^\star\),定义 \(x\equiv_Ly\),当且仅当 \(\forall z\in\Sigma^\star,xz\in L\equiv yz\in L\)。语言 \(L\) 的最小 DFA 状态数就是等价关系 \(\equiv_L\) 在 \(\Sigma^\star\) 上划分出的等价类数目。

  直接考虑 \(L\) 的最小 DFA 的形态,可以发现:

  • 对于任意状态,从开始状态转移到它的路径长度唯一;
  • 不存在两个状态的转移完全相同(输入同样字符,转移向同一个状态)。

  根据性质一,我们将 DFA 的 DAG 分层,那么总状态数就是每层的状态数之和。令 \(Q_i~(i=0,1,\dots,m)\) 为第 \(i\) 层的状态,则 \(Q_0=\{q_s\}\) 为开始状态,\(Q_m=\{q_t\}\) 为唯一接受状态,此时对于第 \(k\) 层,从 \(Q_{k-1}\) 对 \(Q_k\) 的限制来看,显然 \(|Q_k|\le2|Q_{k-1}|\);从 \(Q_{k+1}\) 对 \(Q_k\) 的限制来看,为了满足性质二,\(Q_{k+1}\) 最多为 \(Q_k\) 内的某个点提供 \((|Q_{k+1}|+1)^2-1\) 种转移的选择(\(1\) 表示空状态,即分别枚举 \(\texttt a\) 和 \(\texttt b\) 转移向谁,不能同时为空)。根据这一构造,每个 \(|Q_k|\) 的上界显然可以同时取到,所以第一问就解决了。

  设 \(Q_p\) 为最后一层满足 \(Q_p=2|Q_{p-1}|\) 的状态,此后,\(Q_k\) 的大小都将由性质二的限制决定。前后都已经固定,\(|L|\) 只取决于 \(\delta_p:Q_p\times\Sigma\rightarrow Q_{p+1}\) 的长相。

  先来刻画 \(Q_{p+1}\) 内每个点对应的后缀串数量。令 \(G_k(x)~(k=p+1,\dots,m)\) 表示 \(Q_k\) 中,状态数量关于状态对应后缀串数量的 GF,那么 \(G_k(x)=(G_{k+1}(x)+1)^2-1\),其实就是 \(G_k(x)=(x+1)^{2^{m-k}}-1\)。

  然后,讨论一下 \(|Q_p|\) 和 \(|Q_{p+1}|\) 的大小关系:

  若 \(|Q_p|<|Q_{p+1}|\),注意到此时必然有 \(|Q_{p+1}|=2|Q_p|+1\),\(\delta_p\) 的当务之急是让每个 \(q\in Q_{p+1}\) 都有前驱。因此先让 \(Q_p\) 内每个点随便在 \(Q_{p+1}\) 里连两个,剩下一个状态放弃一个转移最小化 \(|L|\),增加一个到 \(Q_{p+1}\) 内后缀最多的状态的转移最大化 \(|L|\)。

  若 \(|Q_p|\ge|Q_{p+1}|\),我们需要同时关注“每个状态都有前驱”以及“最小/最大化 \(L\)”的要求。先描述出“在 \(Q_{p+1}\) 里连两个后继”的贡献,令 \(F(x)\) 表示连接方案数关于连接到后继的后缀总数的 GF,那么 \(F(x)=(G_{p+1}(x)+1)^2-1=(x+1)^{2^{m-p+1}}-1\)。接着贪心考虑最小化与最大化 \(L\) 的构造方案:

  • 最小化 \(|L|\),先用 \(Q_p\) 内的 \(|Q_{p+1}|\) 个状态直接各自连一条转移边到 \(Q_{p+1}\) 内的状态,求到剩下能选的连接方案的 GF \(F_1(x)\),在 \(F_1(x)\) 里按指标升序贪心选择。
  • 最大化 \(|L|\),先用 \(Q_p\) 内的 \(|Q_{p+1}|\) 个状态直接各自连一条转移边到 \(Q_{p+1}\) 内的状态,再连一条转移边到 \(Q_{p+1}\) 内后缀串最多的状态,其余和最小化类似。

  撇开高精度计算,复杂度是 \(\mathcal O(n)\) 的。

\(\mathcal{Code}\)

# Rainybunny #

import sys

if __name__ == "__main__":
sys.stdin = open('dfa.in', 'r')
sys.stdout = open('dfa.out', 'w') n = int(input())
ans = [0 for _ in range(3)] m = 0
while 1 << m + 1 <= n - m - 1: m += 1
## the last limited level's G.F. is f_m(x)=(x+1)^{2^m}-1.
# sys.stderr.write(str(m) + '\n') ans[0] = (1 << n - m) - 1
for i in range(0, m + 1):
ans[0] += (1 << (1 << i)) - 1 lef = 1 << n - m - 1; rig = (1 << (1 << m)) - 1
if (lef < rig):
sys.stderr.write('type 1\n')
ans[1] = 1 << ((1 << m) + m - 1)
ans[2] = ans[1] + (1 << m)
else:
sys.stderr.write('type 2\n')
## get f_m(x)(->bino[0]) and f_m^2(x)(->bino[1])
bino = [[0 for _ in range((1 << m) + 1)],
[0 for _ in range((1 << m + 1) + 1)]]
bino[0][0] = bino[1][0] = 1
for i in range(1, (1 << m) + 1):
bino[0][i] = bino[0][i - 1] * ((1 << m) - i + 1) // i
for i in range(1, (1 << m + 1) + 1):
bino[1][i] = bino[1][i - 1] * ((1 << m + 1) - i + 1) // i ## get ans[1].
for i in range(1, (1 << m) + 1):
ans[1] += i * bino[0][i]
bino[1][i] -= bino[0][i]
rest = lef - rig; cur = 1
while rest and rest > bino[1][cur]:
ans[1] += bino[1][cur] * cur
rest -= bino[1][cur]
cur += 1
ans[1] += cur * rest ## get ans[2].
for i in range(1, (1 << m) + 1):
ans[2] += bino[0][i] * (i + (1 << m))
bino[1][i] += bino[0][i] # recover it
bino[1][i + (1 << m)] -= bino[0][i]
rest = lef - rig; cur = 1 << m + 1
while rest and rest > bino[1][cur]:
ans[2] += bino[1][cur] * cur
rest -= bino[1][cur]
cur -= 1
ans[2] += cur * rest print("%d %d %d" % (ans[0], ans[1], ans[2])) sys.stdin.close()
sys.stdout.close()

Solution -「LOCAL」Minimal DFA的更多相关文章

  1. Solution -「LOCAL」二进制的世界

    \(\mathcal{Description}\)   OurOJ.   给定序列 \(\{a_n\}\) 和一个二元运算 \(\operatorname{op}\in\{\operatorname{ ...

  2. Solution -「LOCAL」大括号树

    \(\mathcal{Description}\)   OurTeam & OurOJ.   给定一棵 \(n\) 个顶点的树,每个顶点标有字符 ( 或 ).将从 \(u\) 到 \(v\) ...

  3. Solution -「LOCAL」过河

    \(\mathcal{Description}\)   一段坐标轴 \([0,L]\),从 \(0\) 出发,每次可以 \(+a\) 或 \(-b\),但不能越出 \([0,L]\).求可达的整点数. ...

  4. Solution -「LOCAL」Drainage System

    \(\mathcal{Description}\)   合并果子,初始果子的权值在 \(1\sim n\) 之间,权值为 \(i\) 的有 \(a_i\) 个.每次可以挑 \(x\in[L,R]\) ...

  5. Solution -「LOCAL」Burning Flowers

      灼之花好评,条条生日快乐(假装现在 8.15)! \(\mathcal{Description}\)   给定一棵以 \(1\) 为根的树,第 \(i\) 个结点有颜色 \(c_i\) 和光亮值 ...

  6. Solution -「LOCAL」画画图

    \(\mathcal{Description}\)   OurTeam.   给定一棵 \(n\) 个点的树形随机的带边权树,求所有含奇数条边的路径中位数之和.树形生成方式为随机取不连通两点连边直到全 ...

  7. Solution -「LOCAL」ZB 平衡树

    \(\mathcal{Description}\)   OurOJ.   维护一列二元组 \((a,b)\),给定初始 \(n\) 个元素,接下来 \(m\) 次操作: 在某个位置插入一个二元组: 翻 ...

  8. Solution -「LOCAL」舟游

    \(\mathcal{Description}\)   \(n\) 中卡牌,每种三张.对于一次 \(m\) 连抽,前 \(m-1\) 次抽到第 \(i\) 种的概率是 \(p_i\),第 \(m\) ...

  9. Solution -「LOCAL」充电

    \(\mathcal{Description}\)   给定 \(n,m,p\),求序列 \(\{a_n\}\) 的数量,满足 \((\forall i\in[1,n])(a_i\in[1,m])\l ...

  10. Solution -「LOCAL」「cov. 牛客多校 2020 第五场 C」Easy

    \(\mathcal{Description}\)   Link.(完全一致)   给定 \(n,m,k\),对于两个长度为 \(k\) 的满足 \(\left(\sum_{i=0}^ka_i=n\r ...

随机推荐

  1. Oracle HR样例数据库建立

    在视频的学习过程中,老师用到了HR样例数据库,但是我发现我的样例数据库中没有HR样例数据库,可能是在安装的时候漏掉了哪个环节,所以只能补救一下 如何判断自己是否有HR样例数据库呢?操作代码如下所示 第 ...

  2. Java面试题中高级进阶(JVM篇01)

    前言 本来想着给自己放松一下,刷刷博客,突然被几道面试题难倒!说说堆和栈的区别?什么时候会触发FullGC?什么是Java虚拟机?似乎有点模糊了,那就大概看一下面试题吧.好记性不如烂键盘 *** 12 ...

  3. VS项目无法加载js或其他文件

    1.查看文件位置项目是否加载进去 2.将文件显示,再次找到该目录将文件添加到项目中 3.启动调试,

  4. 使用越来越广泛的2FA双因素认证,缘何越发受到推崇?

    大家好,我是vzn呀,又见面了. 随着互联网在生活方方面面的应用,日常少不了要登录各个网站或者应用.或者是银行转账等需要验证自己身份的场景.从早期的输入账号密码来登录,到后来普遍开始通过手机验证码进行 ...

  5. ES6 延展操作符

    延展操作符(Spread operator) 延展操作符 = ...可以在函数调用/数组构造时,将数组表达式或者string在语法层面展开,还可以在构造对象时,将对象表达式按key-value的方式展 ...

  6. 孤立森林(IForest)代码实现及与PyOD对比

    孤立森林(Isolation Forest)是经典的异常检测算法(论文网址).本文用python对其进行实现,以及与常用的异常检测包PyOD进行效果对比. 简单来说,孤立森林(IForest)中包含若 ...

  7. x-easypdf 初始

    一.概述 一个 java 语言简化处理 pdf 的框架 项目主页 https://x-easypdf.cn 项目概述 x-easypdf是一个java语言简化处理pdf的框架,包含fop模块与pdfb ...

  8. 无快不破,在本地 docker 运行 IDEA 里面的项目?

    目录 前言 Docker Compose 1. Docker Compose是什么? 2. Docker Compose 的具体步骤 3. 如何在IDEA项目里面使用Docker Compose 启动 ...

  9. JDBC基础知识

    常见连接数据库工具: 图形化工具:点击.拖拽就可以操作数据库,对用户友好,简单对数据操作,复杂数据库操作爱莫能助 JDBC(驱动程序):调用jar包接口 窗口(命令行):输入完整SQL语句对复杂数据库 ...

  10. 开源的 Linux 游戏平台「GitHub 热点速览」

    <越狱>.<迷失>.<西部风云>等经典美剧背后的民间字幕翻译团队--人人影视,由于 AI 翻译的崛起.官方中文字幕的普及和版权问题,最终决定以开源的方式,为这段旅程 ...