Find repeating substring of Length N
我必须制作一个Java程序,它找到给定字符串中所有长度为n的子字符串。输入字符串非常长,而暴力方法需要花费太多时间。
我试过:目前,我将分别查找每个子字符串,并使用kmp算法检查该子字符串的重复。这也花费了太多时间。
对于这个问题,什么方法更有效?
- 要求我们推荐或查找书籍、工具、软件库、教程或其他非现场资源的问题是堆栈溢出的主题,因为它们往往会吸引固执己见的答案和垃圾邮件。相反,描述这个问题以及迄今为止为解决它所做的工作。
- 不知道为什么这个问题被否决为"太宽泛"——手头有一个具体的问题,@program-dude还提供了他所尝试的以及失败的原因。
- @以利雅户就是这样。
- @阿米特他做了什么?他要密码?所以这不是主题
- @伊利亚胡完全是在谈这个话题。他描述了一个问题,描述了一个解决方案,解释了建议的解决方案失败的原因,并要求提供一个替代方案。比"如何解析字符串"更"高级"的问题?是一个完美的话题。
- 您必须共享一些代码,这样,如果有人能够回答您的问题,您的问题可以引导您到代码中的特定点,以增强或更改,否则,任何人都必须解决整个问题,才能呈现SOL。这不是这个网站的目的,这就是为什么你的问题被选为1(0)
- @amit,尤其是在编辑完删除问题部分后
- 我认为太宽泛,可能的答案太多,或者好的答案对于这种格式来说太长。请添加详细信息以缩小答案集或隔离一个可以在几个段落中回答的问题。适合这里,OP不仅要求一个答案,而且要求最好的答案,一个快速的答案,这将以某种方式偏离主题。
- @雅赞在这些问题上你看到代码了吗:一双袜子从一堆,算法的改进为可口可乐可以形状识别,纯英文解释的大O?然而,他们完全是在讨论这个问题。
- @Eliyahu这就是我们拥有编辑能力的原因,作为一个经验丰富的用户,我们可以很容易地让问题变得更容易理解和完美。投票结束前应使用这些工具。
- @阿米特,我不想仅仅为了争论而争论这个问题,而且很高兴你提出了一些更老的问题,很明显这些问题比这个问题更好更高的质量。这是我的观点,我甚至没有投反对票或标记这个问题,只是说:)
- @amit如果是这样,也应该有一个选项来删除审阅者的审阅标志。我在你编辑之前看到这个问题,它很糟糕,我建议删除/编辑它。在你编辑之后,这个问题看起来更好了,所以我的旗帜会有争议,甚至会倾斜。你觉得公平吗?
1)应该使用后缀树数据结构。
后缀树
这个数据结构可以在O(n*log n)时间内构建(我认为即使在O(N)时间内,使用Ukkonen算法)其中n是输入字符串的大小/长度。这样就可以解决许多(否则)困难的问题。o(m)时间内的任务,其中m是模式的大小/长度。
所以即使我没试过你的问题,我也很确定如果使用后缀树和问题的智能公式,则使用后缀树(在合理的时间内)可以解决问题。
2)关于这些(和相关)主题的一本非常好的书是:
字符串、树和序列的算法
不过,除非你在算法方面受过良好的训练,否则阅读起来并不容易。但好吧,阅读这些东西是获得良好训练的唯一途径;)
3)我建议您也快速了解一下这个算法。
AHO Corasick算法
虽然,我不确定,但是…这个可能有点与你的特定问题无关的话题。
我将采纳@peter.petrov的建议,并通过解释人们如何实际使用后缀树来解决这个问题来加强它:
1 2 3 4 5
| 1. Create a suffix tree from the string, let it be `T`.
2. Find all nodes of depth `n` in the tree, let that set of nodes be `S`. This can be done using DFS, for example.
3. For each node `n` in `S`, do the following:
3.1. Do a DFS, and count the number of terminals `n` leads to. Let this number be `count`
3.2. If `count>1`, yield the substring that is related to `n` (the path from root to `n`), and `count` |
请注意,该算法处理长度为n的任何子串,并将其添加到设置的S中,然后从中通过计算该子串所指向的终端数来搜索该子串实际是子串的次数。
这意味着问题的复杂性是O(Creation + Traversal),也就是说,首先创建树,然后遍历它(很容易看到,在步骤2-3中,树中的每个节点不会多次遍历)。由于遍历明显比树的创建"快",因此它会让您得到O(Creation),正如@perer.petrov指出的那样,根据您选择的算法,O(|S|)或O(|S|log|S|)是O(|S|)或O(|S|log|S|)。