1 条题解
-
0
Guest
-
0
答案与解析
(1)
判断题
-
正确 (✔)
- 解析: 这是 KMP 算法中
pi数组(或称next数组)的标准定义。pi[i]的值被定义为模式串p从索引 0 到i的子串p[0...i]中,同时是其前缀和后缀的最长公共部分的长度。例如,对于 "ababa",pi[4]是子串 "ababa" 的最长公共前后缀 "aba" 的长度,即 3。
- 解析: 这是 KMP 算法中
-
错误 (✘)
- 解析: 标准的 KMP 算法在
if (j == m)的代码块中会包含一个计数器,并且通常会将j重置为pi[j-1]以便继续寻找下一个可能的匹配(包括重叠的匹配)。此程序虽然在匹配成功后正确地将j更新为pi[j-1],但它没有设置任何变量来统计匹配发生的次数。因此,它不具备计数功能。
- 解析: 标准的 KMP 算法在
-
正确 (✔)
- 解析:
- 首先,
compute_pi("aba")计算出的pi数组为{0, 0, 1}。 - 程序开始在文本串
t("abababa") 中匹配模式串p("aba")。 i=0,1,2:t的 "aba" 与p匹配,j变为3。j == m(3 == 3) 条件成立,程序执行j = pi[j-1] = pi[2] = 1。i=3:t[3]('b') 与p[j](p[1]='b') 匹配,j变为2。i=4:t[4]('a') 与p[j](p[2]='a') 匹配,j变为3。j == m条件再次成立,j再次被更新为1。i=5:t[5]('b') 与p[j](p[1]='b') 匹配,j变为2。i=6:t[6]('a') 与p[j](p[2]='a') 匹配,j变为3。j == m条件又一次成立,j更新为1。- 循环结束,
j的最终值为1,因此程序输出1。
- 首先,
- 解析:
选择题
-
B. 文本串
t的后缀能够与模式串p的前缀匹配的最大长度- 解析: 整个
for循环可以看作一个状态机(KMP 自动机)在处理文本串t。变量j代表当前状态,即已经匹配上的模式串p的前缀长度。当循环遍历完整个t后,j的最终值就表示t的后缀与p的前缀能够匹配的最大长度。
- 解析: 整个
-
D. 4
- 解析:
p= "abraca",pi数组为{0, 0, 0, 1, 0, 1}。t= "abracadabra"。- 当
i从0遍历到5时,t的前缀 "abraca" 与p完全匹配,j变为6。 - 此时
j == m(6 == 6) 成立,j被更新为pi[5] = 1。 - 继续遍历
t:i=6, t[6]='d',p[1]='b'. 不匹配。j更新为pi[j-1]=pi[0]=0。i=7, t[7]='a',p[0]='a'. 匹配。j变为1。i=8, t[8]='b',p[1]='b'. 匹配。j变为2。i=9, t[9]='r',p[2]='r'. 匹配。j变为3。i=10, t[10]='a',p[3]='a'. 匹配。j变为4。
- 循环结束,
j的最终值为4。
- 解析:
(2)
判断题
-
正确 (✔)
- 解析: 该程序通过深度优先搜索(DFS),并使用
dfn(discovery time number) 和low(low-link value) 数组来识别图中的桥,这是 Tarjan 桥边查找算法的典型实现。low[v] > dfn[u]是判断边(u, v)是否为桥的核心条件。
- 解析: 该程序通过深度优先搜索(DFS),并使用
-
错误 (✘)
- 解析:
low[u]被定义为从u出发,通过其在DFS树中的子树,能到达的节点的最小dfn值。low[u]的初始值为dfn[u],之后它只可能通过min操作变得更小或保持不变。因此,恒有low[u] <= dfn[u]。题目中的dfn[u] <= low[u]是错误的。
- 解析:
-
正确 (✔)
- 解析:
low[v] > dfn[u]表示从节点v的子树出发,无法通过返祖边到达u或u的任何祖先节点,因此(u,v)是桥。如果low[v] == dfn[u],表示从v的子树出发最远只能到达u,这意味着存在一个环恰好经过边(u,v),所以(u,v)不是桥。若将条件改为>=,就会将这种在环上的边错误地判断为桥。
- 解析:
选择题
-
C. 节点
u及其在 DFS 树中的所有后代,能通过返祖边到达的节点的最小时间戳- 解析: 这是
low-link值的标准定义。它综合考虑了两种情况:一是通过u的子节点v递归计算出的low[v];二是通过从u直接连接到已访问过的邻居v的返祖边dfn[v]。最终low[u]是这些值中的最小值。
- 解析: 这是
-
D. 3
- 解析:
- 给定的边构成了下图:
1-2,2-3,3-1形成一个三角形的环。节点3连接一个链条3-4-5-6。 - 在一个环内的边 (
1-2,2-3,3-1) 都不是桥,因为移除任何一条,环内节点依然连通。 - 边
3-4,4-5,5-6是桥。移除3-4会使{1,2,3}和{4,5,6}断开。同理,移除4-5或5-6也会导致图断开。 - 因此,图中共有 3 条桥。
- 给定的边构成了下图:
- 解析:
(3)
判断题
-
正确 (✔)
- 解析: 函数
count_inversions采用了分治策略。它将数组分成两半,递归地计算左右两半的逆序对数,然后在合并(merge)两个有序子数组的过程中,计算跨越两部分的逆序对数。这个结构与归并排序完全一致,只是在合并步骤中增加了计数的逻辑。
- 解析: 函数
-
正确 (✔)
- 解析: 在竞赛题目中,若未特殊说明,输入的序列通常被假定为某个范围整数的一个排列(permutation),即不含重复元素。在此前提下,
pos_a[a[i]] = i;的作用是建立一个从数值到其在数组a中唯一索引的映射。说“第一次出现的位置”是正确的,因为每个元素只会出现一次。
- 解析: 在竞赛题目中,若未特殊说明,输入的序列通常被假定为某个范围整数的一个排列(permutation),即不含重复元素。在此前提下,
-
正确 (✔)
- 解析: 如果序列
a和b完全相同,那么b[i] = a[i]。在构造数组p时,p[i] = pos_a[b[i]] = pos_a[a[i]]。而pos_a[a[i]]的值就是i。因此,数组p将会是{0, 1, 2, ..., n-1}。这是一个完全有序的序列,其逆序对数量为 0。
- 解析: 如果序列
选择题
-
D. 计算序列
p的逆序对数量- 解析: 从程序的结构看,
main函数的核心任务是构造序列p,然后调用count_inversions(p, 0, n - 1)并输出其返回值。因此,程序最直接、最准确的功能描述就是计算序列p的逆序对数量。 - 延伸解读: 这个问题有更深层的含义。构造出的序列
p的逆序对数,等价于“将序列b变换为序列a所需的最少相邻交换次数”,也等于“在a和b中相对顺序不同”的数对的数量。在选项中,B 选项没有指明是“相邻”交换,这可能引起歧义(非相邻交换的最少次数是n - 环的个数)。C 选项是正确的解释,但 D 选项是程序行为最直接的描述。在阅读程序题中,选择最直接描述程序计算行为的选项通常是最稳妥的。
- 解析: 从程序的结构看,
-
D. 10
- 解析:
n=5a = {1, 2, 3, 4, 5}b = {5, 4, 3, 2, 1}- 首先,根据
a创建位置映射pos_a:pos_a[1]=0,pos_a[2]=1,pos_a[3]=2,pos_a[4]=3,pos_a[5]=4。 - 然后,根据
b和pos_a构造序列p:p[0] = pos_a[b[0]] = pos_a[5] = 4p[1] = pos_a[b[1]] = pos_a[4] = 3p[2] = pos_a[b[2]] = pos_a[3] = 2p[3] = pos_a[b[3]] = pos_a[2] = 1p[4] = pos_a[b[4]] = pos_a[1] = 0
- 所以
p = {4, 3, 2, 1, 0}。 - 最后,计算
p的逆序对数量。这是一个完全逆序的长度为 5 的序列。对于任何一对索引(i, j)且i < j,都有p[i] > p[j],因此任意一对元素都构成逆序对。 - 总逆序对数量为
C(5, 2) = 5 * (5 - 1) / 2 = 10。
- 解析:
-
- 1
信息
- ID
- 9961
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 1
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者