一尘不染

寻找最小语法窗口的有效算法?

algorithm

一个 pangrammatic窗口
是一个包含字母的所有26个字母一块较大的文本的字符串。在给出以下文字的情况下,引用维基百科的示例:

我唱歌,以为我唱歌很好。但是他只是以一种非常古怪的表情抬头看着我的脸,说道:“你唱歌多久了,小姐?”

文本中最小的语法窗口是以下字符串:

很好 但他只是带着一个非常古怪的前夫抬头看着我的脸

实际上每个字母至少包含一次。

我的问题是: 给定文本语料库,查找文本中最小的语法窗口的最有效算法是什么?

我已经考虑了一下,并已经提出了以下算法。我强烈认为这些不是最佳选择,但我认为我应该将它们作为起点。

有一个简单的天真算法可以在时间O(n 2)和空间O(1)中运行:对于字符串中的每个位置,从该位置向前扫描并跟踪您看到的字母(也许在位向量中,
,因为只有26个不同的字母,所以需要空格O(1))。找到所有26个字母后,您便拥有从该给定点开始的最短的语法窗口的长度。每次扫描可能花费时间O(n),并且有O(n)次扫描,总共需要O(n
2)时间。

我们还可以使用改进的二进制搜索在时间O(n log
n)和空间O(n)上解决此问题。构造26个数组,每个字母对应一个字母,然后按输入顺序将每个字母在输入文本中的位置填充到这些数组中。我们可以通过简单地扫描文本,将每个索引附加到与当前字符相对应的数组上来完成此操作。一旦有了这个,我们就可以在时间O(log
n)中找到最短的语法窗口的长度,该长度是从某个索引开始的,方法是在数组中运行26个二进制搜索以查找每个字符最早出现在输入数组中的时间,即或在给定索引之后。这些数字中的最大者为“长杆”字符,该字符出现在字符串的最下方,从而给出语法窗口的终点。

对上述方法的进一步改进是用van Emde
Boas树
和以前的搜索替换数组和二进制搜索。对于使用O(n)空间使用的O(n
log log n)净运行时间,这将创建时间增加到O(n log log n),但将每个搜索时间减少到O(log log n)时间。


有没有更好的算法?


阅读 230

收藏
2020-07-28

共1个答案

一尘不染

该算法具有O(M)个空间复杂度和O(N)个时间复杂度(时间不取决于字母大小M):

  1. 推进第一个迭代器,并为每个处理的字母增加计数器。当所有26个计数器都不为零时停止。
  2. 推进第二个迭代器,并减少每个处理过的字母的计数器。当这些计数器中的任何一个为零时停止。
  3. 使用迭代器之间的差异来更新最新结果,然后继续执行步骤1。

如果存储字符串中的位置而不是字符计数器,则可以稍微改进此算法。在这种情况下,步骤2应该只读取这些位置并将其与当前位置进行比较,而步骤1应该更新这些位置并(大部分时间)搜索文本中的某些字符。

2020-07-28