我只是在研究Java String
类的.indexOf()
方法的实现,似乎代码的作者使用强力算法来查找给定字符串中的子字符串。也就是说,该方法在O(mn)中运行,其中m和n分别是源和目标字符串的长度。
为什么作者没有使用像Rabin-Karp这样的更有效的算法,如果提供了良好的哈希函数,它的运行时复杂度为O(m + n)?
我可能会错过这个实现原因背后的完整知识,因此想要理解。
答案 0 :(得分:15)
我不确定为什么做出这个决定,但是如果我猜测它可能是因为对于小模式字符串(一个非常常见的用例),天真的暴力算法可能会快一些,如果不快一些渐渐快速的算法,如Rabin-Karp,Boyer-Moore或Knuth-Morris-Pratt。这似乎是一个合理的默认算法,因为在很多情况下你会搜索小字符串以寻找小模式,而强大的匹配设置的开销可能与天真方法的运行时相当。
也就是说,Java规范中没有任何地方要求使用这种算法。他们可以很容易地选择Rabin-Karp作为默认算法。
他们可能选择这种方法的另一个原因是因为如果你想进行快速文本搜索,正则表达式库提供更快的字符串匹配和更强大的搜索功能。默认情况下为用户提供简单的强力算法,并在需要时切换到更强大的工具集,这似乎是平衡渐近效率和实际效率的好方法。
答案 1 :(得分:6)
我假设你的意思是indexOf或包含而不是substring。子串是O(1)
通常简单的代码运行得更快。例如,创建对象的代码通常运行得慢得多。
为什么不尝试自己实现它,看看它是否更快。如果是,您可以建议他们改进方法。
答案 2 :(得分:0)
我猜他们并不认为人们会将它用于非常大的字符串。如果字符串长度小于100,则不会有太大差异。
答案 3 :(得分:0)
只是一个猜测,但请记住 Java String存储为UTF-16 ,原因是i18n,而不是普通的8位ASCII。可能是支持UTF-16上的一些算法(以及更难的UTF-8)可能会有问题。不过只是一个猜测。