最小的重复子串

Lui*_*hys 4 scala

我正在看一个Perl 代码高尔夫页面(不要问为什么)并且遇到了这个:

第3洞 - 最小的重复模式

编写一个接受字符串的子例程,该字符串可能包含重复模式,并返回最小的重复子字符串.如果字符串不包含重复模式,则子例程应返回undef或空字符串.例如:

input    output 
'aaaaaa' 'a' 
'ababab' 'ab' 
'aabaab' 'aab' 
'ababaa' ''
Run Code Online (Sandbox Code Playgroud)

显然在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("")
Run Code Online (Sandbox Code Playgroud)

huy*_*hjl 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, "")
Run Code Online (Sandbox Code Playgroud)

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

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

还有一个,使用grouped:

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


Tra*_*own 7

你愿意承认Regex基于解决方案吗?

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

或者单行:

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

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