最小的重复子串

时间:2011-10-25 01:17:33

标签: scala

我正在看Perl code golf page(不要问为什么)并且遇到了这个:

  

第3洞 - 最小重复模式

     

编写一个子程序,接受一个可能由a组成的字符串   重复模式,并返回最小的重复子字符串。如果   字符串不包含重复模式,即子例程   应该返回undef或空字符串。 e.g:

input    output 
'aaaaaa' 'a' 
'ababab' 'ab' 
'aabaab' 'aab' 
'ababaa' ''

显然在Perl中,这可以表示为sub g3 { pop=~/^(.*?)\1+\z/s&&$1 }

我不太了解Perl,所以我不明白它是如何工作的。我们在Scala能做的最好的事情是什么?我对优雅感兴趣而不是精确的角色数。

这是我的尝试,但这很难看,这就是我要问的原因。

def srp(s: String) =
  s.inits.toList.tail.init.map(i => (i * (s.size / i.size), i)).
    filter(_._1 == s).map(_._2).reverse.headOption.getOrElse("")

3 个答案:

答案 0 :(得分:7)

优雅是主观的......

def smallestPat(input: String) = {
   (1 to input.length).view
      .map(i => input.take(i))
      .find{p => 
        Iterator.iterate(p)(_ + p)
          .takeWhile(_.length <= input.length)
          .exists(_ == input) && p != input}
      .getOrElse("")
}

List("aaaaaa", "ababab", "aabaab", "ababaa") map smallestPat
// res13: List[String] = List(a, ab, aab, "")

编辑并重新编辑:略微缩短:

def smallestPat(i: String) = {
   (1 to i.length - 1)
      .map(i.take)
      .find(p => p * (i.length / p.length) == i)
      .getOrElse("")
}

再使用grouped

def smallestPat(i: String) = {
  (1 to i.size/2).map(i.take)
  .find(p => i.grouped(p.size) forall(p==))
  .getOrElse("")
}

答案 1 :(得分:7)

您是否愿意接受基于Regex的解决方案?

def srp(s: String) = {
  val M = """^(.*?)\1+$""".r
  s match {
    case M(m) => Some(m)
    case _ => None
  }
}

或者单行:

val srp = """^(.*?)\1+$""".r.findFirstMatchIn(_: String).map(_.group(1))

不像Perl那样简洁,但我发现两者都更具可读性。

答案 2 :(得分:2)

这是等效的Scala单行程序:

"""(?:^(.*?)\1+$)|.*""".r replaceAllIn (_: String, "$1")