您能否根据以下内容提出循环字符串的规范化函数:
- 找到最大的零运行。
- 旋转字符串,使零的运行在前面。
- 对于每个大小相等的零,看看是否将其旋转到前面会产生一个字典顺序较小的字符串,如果是,则使用它。
这会将等价类(1011、1101、1110、0111)中的所有内容规范化为字典上的最小值:0111。
0101010101
是一个棘手的例子,这个算法不能很好地执行,但如果你的位大致随机分布,它应该在实践中很好地处理长字符串。
然后,您可以根据规范形式进行散列,或使用仅包含空字符串和以 0 开头的字符串的 trie,运行一次 trie 即可回答您的问题。
编辑:
如果我有一个长度为 |s| 的字符串 找到最小的词典价值可能需要很多时间。实际需要多少时间?
这就是为什么我010101....
说它表现不佳的价值。假设字符串的长度为 n,最长的 1 的长度为 r。如果位是随机分布的,根据“最长运行的分布”,最长运行的长度为 O(log n) 。
找到最长运行的时间是 O(n)。您可以使用偏移量而不是缓冲区副本来实现移位,这应该是 O(1)。运行次数是最坏情况 O(n / m)。
那么,执行第 3 步的时间应该是
- 寻找其他长期运行:一个 O(n) 通过 O(log n) 存储平均情况,O(n) 最坏情况
- 对于每次运行:O(log n) 平均情况,O(n) 最坏情况
- 按字典顺序移位和比较:O(log n) 平均情况,因为随机选择的字符串的大多数比较早期失败,O(n) 最坏情况。
这导致 O(n²) 的最坏情况,但 O(n + log² n) ≅ O(n) 的平均情况。