假设我有两个字符串:s
和t
。我需要编写一个函数f
来查找最大值。 t
前缀,也是s
后缀。例如:
s = "abcxyz", t = "xyz123", f(s, t) = "xyz"
s = "abcxxx", t = "xx1234", f(s, t) = "xx"
你会怎么用Scala写的?
答案 0 :(得分:4)
这个第一个解决方案很简单,也比递归版本更有效,因为它使用了一个懒惰的迭代评估
s.tails.find(t.startsWith).get
现在已经讨论过tails
是否会反复复制整个字符串。在这种情况下,您可以toList
使用s
,然后使用mkString
结果。
s.toList.tails.find(t.startsWith(_: List[Char])).get.mkString
由于某种原因,需要使用类型注释来进行编译。我实际上并没有尝试看哪一个更快。
更新 - 优化
正如som-snytt指出的那样,t
不能以任何比它长的字符串开头,因此我们可以进行以下优化:
s.drop(s.length - t.length).tails.find(t.startsWith).get
答案 1 :(得分:3)
如果我们只需要找到公共重叠部分,那么我们可以递归地获取第一个字符串的尾部(它应该与第二个字符串的开头重叠),直到剩下的部分不是第二个字符串开头的部分。 。这也涵盖了字符串没有重叠的情况,因为那时将返回空字符串。
scala> def findOverlap(s:String, t:String):String = {
if (s == t.take(s.size)) s else findOverlap (s.tail, t)
}
findOverlap: (s: String, t: String)String
scala> findOverlap("abcxyz", "xyz123")
res3: String = xyz
scala> findOverlap("one","two")
res1: String = ""
更新:有人指出tail
可能无法以最有效的方式实现(即它在调用时会创建一个新字符串)。如果这成为问题,那么使用substring(1)
代替tail
(或将两个字符串转换为列表,其尾部/头部应具有O(1)复杂度)可能会提供更好的性能。同样,我们可以将t.take(s.size)
替换为t.substring(0,s.size)
。
答案 2 :(得分:3)
效率高,这不是,但它是一个整洁的(IMO)单线。
val s = "abcxyz"
val t ="xyz123"
(s.tails.toSet intersect t.inits.toSet).maxBy(_.size)
//res8: String = xyz
(取s的所有后缀,也是t的前缀,并选择最长的)