本文主要是介绍4077 k显性字符(枚举技巧),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1. 问题描述:
给定一个由小写字母构成的字符串 s。字符 c 被称为字符串 s 的 k 显性字符,当且仅当字符串 s 的所有长度不小于 k 的子串都包含字符 c。对于给定的字符串 s,请你找到一个最小的 k,使得 s 中至少存在一个 k 显性字符。
输入格式
一个由小写字母构成的字符串 s。
输出格式
一个整数,表示 k 的最小可能值。
数据范围
前 6 个测试点满足 1 ≤ |s| ≤ 10。
所有测试点满足 1 ≤ |s| ≤ 10 ^ 5。
输入样例1:
abacaba
输出样例1:
2
输入样例2:
zzzzz
输出样例2:
1
输入样例3:
abcde
输出样例3:
3
来源:https://www.acwing.com/problem/content/4080/
2. 思路分析:
分析题目可以知道数据规模为10 ^ 5,所以需要考虑如何枚举将时间复杂度控制在O(n)或者O(nlogn)之内,因为需要确定哪一个k显性字符可以使得k最小(k显性字符满足所有长度大于等于k的子串都包含当前的字符),所以我们可以枚举每一个出现的字符c,求解出字符c之间的最大间隔d,可以发现当间隔x小于d之后是不存在所有长度大于等于x之后的所有子串包含当前的字符c,所以对于当前枚举的字符间隔必须大于等于d,答案是否可以取到d呢?如果可以取到d说明对于当前枚举的字符最小的k等于d,我们可以使用反证法证明(很多题目都是类似的答案大于等于某个数,然后看是否可以取到这个数,如果可以取到那个答案就是当前的数字),假设对于当前枚举的字符c答案大于等于d + 1,说明所有字符c的间隔必须大于d之后才能够使得所有长度大于等于d + 1的子串都包含字符c,但是存在一个长度为d的子串使得包含当前的字符c,所以就矛盾了,那么答案可以取到d;因为对于当前枚举的字符c,答案大于等于d,而且可以取到d,所以答案就是d,我们可以枚举所有的字符c,求解字符c之间的最大间隔,在所有枚举的字符中取一个最小值就是答案,可以声明两个数组last和d,其中last[i]表示i对应的字符出现的上一次的位置,d[i]表示i对应的字符的最大间隔,对于第一次出现的字符那么上一次出现的位置就是0,并且还需要枚举最后一段的间隔,也即字符最后一次出现的位置到字符串末尾的位置之间的间隔更新一下最大值即可。
3. 代码如下:
class Solution:def process(self):s = input()M = 26# last记录对应字母出现的上一个位置, d记录对应字母之间的最大间隔last, d = [0] * M, [0] * Mn = len(s)# 注意下标从1开始, 方便计算长度for i in range(1, n + 1):t = ord(s[i - 1]) - ord("a")d[t] = max(d[t], i - last[t])last[t] = i# 计算最后一段的长度for i in range(1, n + 1):t = ord(s[i - 1]) - ord("a")# 注意是减去上一段的长度d[t] = max(d[t], n - last[t])# 因为需要求解最小值将结果置为n + 1res = n + 1for i in range(n):t = ord(s[i]) - ord("a")res = min(res, d[t])return resif __name__ == '__main__':print(Solution().process())
这篇关于4077 k显性字符(枚举技巧)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!