Elixir找到字符串中最长的子字符串

问题描述 投票:0回答:2

我的问题与Find the longest substring in a string完全相同

但与长生不老药有关

我当前的实现非常难看:

str = "aabbbssssssggssrrrr"
String.split(str, "") |> Enum.chunk_while([], fn elem, acc ->
  cond do
    (length(acc) == 0) -> 
    {:cont, [elem]}
    (acc == [""]) -> 
      {:cont, [elem]}
    (List.last(acc) == elem) -> 
      {:cont, [elem | acc]}
    true -> 
    {:cont, Enum.reverse(acc), []}
  end
end,
fn
  [] -> {:cont, []}
  acc -> {:cont, Enum.reverse(acc), []}
end) |> Enum.map(fn e -> Enum.reduce(e, "", &<>/2) end) |> Enum.max_by(&String.length/1)

是否有可能像红宝石或至少更短的东西写单线?

elixir
2个回答
0
投票

具有块的链接解决方案非常差。它执行一些绝对不需要的操作,例如拆分,连接等,这可能会大大降低长输入的性能。

最简单的方法是将正则表达式与back reference一起使用。

str = "aabbbssssssggssrrrr"
Regex.scan(~r/(.)\1{1,}/, str, capture: :first)
#⇒ [["aa"], ["bbb"], ["ssssss"], ["gg"], ["ss"], ["rrrr"]]

例如,现在优先选择最长的字符串:

~r/(.)\1{1,}/
|> Regex.scan(str, capture: :first)
|> Enum.sort_by(&-String.length(hd(&1)))
|> hd()
|> hd()
#⇒ "ssssss"

或带有List.flatten/1

~r/(.)\1{1,}/
|> Regex.scan(str, capture: :first)
|> List.flatten()
|> Enum.sort_by(&-String.length(&1))
|> hd()
#⇒ "ssssss"

2
投票

elixirish解决方案是使用Enum.reduce/3,这使该Enum.reduce/3只需输入一次即可。

O(N)
© www.soinside.com 2019 - 2024. All rights reserved.