Maior substring comum

30

Crie um programa ou função que tome uma lista de cadeias como entrada e produza a cadeia mais longa que é uma substring de todas as cadeias de entrada. Se houver várias substrings de comprimento igual e não mais substring, produza qualquer uma delas.

  • Isso pode significar a saída da string vazia.
  • Se houver várias saídas válidas, você poderá produzir qualquer uma delas. Você não precisa fornecer uma saída consistente para uma determinada entrada, desde que a saída seja sempre válida.
  • Sempre haverá pelo menos uma sequência na entrada, mas pode não haver uma sequência não vazia.
  • Todos os caracteres ASCII imprimíveis podem aparecer na entrada. Você pode assumir que esses são os únicos caracteres que aparecem.
  • Você pode receber entrada ou produzir saída por qualquer um dos métodos padrão .
  • As brechas padrão não são permitidas.
  • Isso é - quanto menos bytes de código, melhor.

Casos de teste:

[Inputs] -> [Valid outputs (choose one)]

["hello", "'ello"] -> ["ello"]
["very", "much", "different"] -> [""]
["empty", "", "STRING"] -> [""]
["identical", "identical"] -> ["identical"]
["string", "stRIng"] -> ["st", "ng"]
["this one", "is a substring of this one"] -> ["this one"]
["just one"] -> ["just one"]
["", "", ""] -> [""]
["many outputs", "stuptuo ynam"] -> ["m", "a", "n", "y", " ", "o", "u", "t", "p", "s"]
["many inputs", "any inputs", "ny iii", "yanny"] -> ["ny"]
["%%not&", "ju&#st", "[&]alpha_numeric"] -> ["&"]
Sara J
fonte
Possível duplicada
Adám 25/03
2
@ Adão que pergunta pede o comum sub mais longa seqüência , não substring.
Maçaneta
1
As strings serão apenas alfanuméricas, alfabéticas ou apenas imprimíveis-ascii?
Modalidade de ignorância
@EmbodimentofIgnorance Todos os caracteres ASCII imprimíveis podem aparecer na entrada.
Sara J
2
@ Shaggy Geralmente, não. Se os dois puderem ser distinguidos, significa que undefinednão há uma sequência de saída válida. Se a sequência vazia (ou qualquer outra sequência) for uma saída válida, alegando que não há saída válida está incorreta.
Sara J

Respostas:

8

Python 2 , 82 bytes

f=lambda h,*t:h and max(h*all(h in s for s in t),f(h[1:],*t),f(h[:-1],*t),key=len)

Experimente online!

Pega entrada splatted. Tempo limite para entradas onde a primeira string é longa.

A idéia é pegar substrings das primeiras strings hpara encontrar a mais longa que aparece em todas as strings restantes t. Para fazer isso, ramificamos recursivamente a remoção do primeiro ou do último caractere de h.


Python 2 , 94 bytes

lambda l:max(set.intersection(*map(g,l)),key=len)
g=lambda s:s and{s}|g(s[1:])|g(s[:-1])or{''}

Experimente online!

Um método mais direto. A função auxiliar ggera o conjunto de todas as subseqüências se a função principal leva a mais longa em sua interseção.

xnor
fonte
8

Brachylog (v2), 3 9 bytes

{sᵛ}ᶠlᵒtw

Experimente online!

Programa completo. Entrada da entrada padrão (como uma lista de strings no estilo JSON), saída para saída padrão.

Explicação

{sᵛ}ᶠlᵒtw
 s         Find a substring
  ᵛ          of every element {of the input}; the same one for each
{  }ᶠ      Convert generator to list
     lᵒt   Take list element with maximum length
        w  Output it

Aparentemente, a ordem de desempate snão é a que está em quase todo o resto no Brachylog, portanto, precisamos substituí-lo manualmente para produzir a saída mais longa. (Isso é um pouco frustrante: quatro caracteres extras para a substituição, mais dois caracteres de agrupamento porque o Brachylog não analisa dois metapredicados seguidos.)

O Brachylog's snão retorna substrings vazios, então precisamos de um truque para contornar isso: em vez de enviar uma função (o que normalmente é feito), escrevemos um programa completo, com saída para a saída padrão. Dessa forma, se houver uma substring comum, apenas a produzimos e terminamos. Se não houver uma substring comum, o programa errará - mas ele ainda não imprime nada na saída padrão; portanto, gera a string nula conforme pretendido.

ais523
fonte
1
Eu tentei isso com a entrada ["muitas entradas", "quaisquer entradas", "ny iabii", "yanabny"]. Eu esperava os resultados ab e ny . Mas só consegui o resultado a . Estou fazendo algo errado ?
t-clausen.dk 25/03
1
Ugh, parece que me lembrei da ordem de desempate por serrado, e substituir a ordem de desempate é um pouco caro em termos de bytes. De qualquer forma, faça isso agora, porque é importante que a resposta esteja correta. De alguma forma, nenhum dos casos de teste que eu tentei percebeu a diferença.
ais523 25/03
1
@ ais523 A ordem sproduz substrings é dando primeiro todos os prefixos da entrada (os mais longos primeiro), depois largando o primeiro e repetindo
Kroppeb 25/03
5

Gelatina , 12 6 bytes

Ẇ€f/ṫ0

Experimente online!

Obrigado a @ JonathanAllan por salvar 6 bytes!

Nick Kennedy
fonte
Eu acredito Ẇ€œ&/Ṫḟ0que faria o trabalho e salvaria quatro bytes, já que as sub-strings já estão ordenadas por comprimento, portanto o resultado filtrado será; tudo o que resta é que, quando não há correspondências, a cauda produz um zero e, como temos listas de caracteres garantidas, podemos simplesmente filtrá-las.
Jonathan Allan
também acho que œ&/pode ser substituído por f/salvar aqui outro
Jonathan Allan
Enviei uma solicitação pull (espero) para tornar o resultado da redução de uma lista vazia uma lista vazia (em vez de gerar um TypeError). Se isso for mesclado, acredito que essa resposta possa se transformar em seis dígitos Ẇ€f/ṛ/.
Jonathan Allan
@JonathanAllan parece bom. Obrigado pelas outras dicas - espero que você tenha ficado feliz em incorporá-las.
Nick Kennedy
Sim, minha razão para esses comentários foi permitir que você incorporasse as idéias em sua postagem.
Jonathan Allan
5

Ruby 2.6, 76 59 54 bytes

->a{*w=a;w.find{|r|w<<r.chop<<r[1..];a.all?{|s|s[r]}}}

Experimente online! - Versão Ruby 2.5 (56 bytes)

Quão?

Crie uma lista de possíveis correspondências, inicialmente configuradas para a matriz original. Itere na lista e, se uma string não corresponder, adicione 2 novas strings ao final da lista, cortando o primeiro ou o último caractere. No final, uma correspondência (eventualmente uma string vazia) será encontrada.

Obrigado Kirill L por -2 bytes e histocrata por mais -2

GB
fonte
4

R , 119 116 108 106 bytes

function(S,`?`=nchar,K=max(?S),s=Reduce(intersect,lapply(S,substring,0:K,rep(0:K,e=K+1))))s[which.max(?s)]

Experimente online!

Encontre todas as substrings de cada string, encontre a interseção de cada lista de substrings e, finalmente, retorne (uma de) a mais longa.

-3 bytes graças a Kirill L.

-8 bytes usando em lapply vez de Map

-2 bytes graças a Kirill L. novamente, removendo chaves

Giuseppe
fonte
Não tenho tempo para verificar, mas se não me engano, duas ocorrências de ncharsão suficientes para salvar algo declarando ncharcomo um operador unário.
Kirill L.
@KirillL. sim, é mais curto em 2 bytes. Obrigado! O aliasing listnos dá -3 bytes.
Giuseppe
Você também pode soltar chaves para outro -2
Kirill L.
@KirillL. obrigado! Estou um pouco preocupado que vou começar a fazer isso com o código de produção ...
Giuseppe
esse é o problema do golfe no idioma que você usa todos os dias
MickyT 25/03
4

05AB1E , 14 9 8 bytes

€Œ.«ÃéθJ

-6 bytes graças a @Adnan .

Experimente online ou verifique todos os casos de teste .

Explicação:

€Œ       # Get the substring of each string in the (implicit) input-list
       # Right-reduce this list of list of strings by:
    Ã    #  Only keep all the strings that are present in both list of strings
     é   # Sort by length
      θ  # And pop and push its last item
         # The substrings exclude empty items, so if after the reduce an empty list remains,
         # the last item will also be an empty list,
       J # which will become an empty string after a join
         # (after which the result is output implicitly)
Kevin Cruijssen
fonte
1
Eu acho que €Œ.«Ãõªéθdeve funcionar para 9 bytes.
Adnan
@ Adnan Espere, nós temos uma redução .. Como eu perdi isso. : SI tentou Å«Ã, mas não percebeu que eu deveria ter usado .«Ã.. Obrigado!
Kevin Cruijssen em 25/03
1
Na verdade, acho que €Œ.«ÃéθJdeveria funcionar para 8.
Adnan
4

Zsh , 126 ... 96 bytes

-3 bytes de aritmética para, -6 bytes de implícito "$@"(obrigado roblogic), -5 bytes de remoção desnecessária { }, -1 byte de forma abreviada de for, -1 byte usando repeat, -1 byte usando , -1 byte concatenando for s ($b)com seu corpo, -13 bytes alterando o loop de repetição para algum jaleco de avaliação.

for l
eval a=\( \$l\[{1..$#l},{1..$#l}\] \)&&b=(${${b-$a}:*a})
for s ($b)(($#x<$#s))&&x=$s
<<<$x

Experimente online! Experimente online! Experimente online!

Lemos todas as substrings possíveis na matriz ae, em seguida, definimos ba interseção das matrizes ae b. A construção ${b-$a}substituirá apenas $ana primeira iteração: Ao contrário da expansão entre irmãos ${b:-$a}, ela não substituirá quando bestiver configurada, mas vazia.

for l;                              # implicit "$@"

# === OLD ===
{
    a= i=                           # empty a and i
    repeat $[$#l**2]                # compound double loop using div/mod
        a+=($l[++i/$#l+1,i%$#l+1])  # append to a all possible substrings of the given line
#               1+i/$#l             # 1,1,1...,  1,1,2,2,2,... ...,  n,n
#                       1+i%$#l     # 1,2,3...,n-1,n,1,2,3,... ...,n-1,n
#       a+=( $l[       ,     ] )    # append that substring to the array
# === NEW ===
    eval a=\( \
        \$l\[{1..$#l},{1..$#l}\] \  # The {bracket..expansions} are not escaped
    \) &&
# ===     ===
    b=( ${${b-$a}:*a} )
#         ${b-$a}                   # if b is unset substitute $a
#       ${       :*a}               # take common elements of ${b-$a} and $a
#   b=(               )             # set b to those elements
}
for s ($b)                          # for every common substring
    (( $#x < $#s )) && x=$s         # if the current word is longer, use it
<<<$x                               # print to stdout
GammaFunction
fonte
Como esse bit funciona? a+=( $l[1+i/$#l,1+i%$#l] )
roblogic 26/03
1
@roblogic Acho que expliquei melhor agora, confira a edição. A idéia é fazer um loop para n ^ 2 e usar / e% em vez de usar 2 forloops aninhados
GammaFunction
1
você pode cortar for l in "$@"com simplicidade for l;- é um truque de festa
roblogic 26/03
Eu tenho que dizer, o zsh é muito mais elegante que o bash. Não há nada análogo a essa boa comparação de array AFAIKb=(${${b-$a}:*a})}
roblogic 27/03
1
Você pode fazer algumas coisas legais e não é tão popular. Isso se traduz em adicionar uma resposta zsh à maioria das perguntas que me deparo. : P Se você quer aprender zsh, eu recomendo man zshexpne man zshparamespecialmente. Eu sempre os tenho abertos ao escrever uma resposta.
GammaFunction 27/03
3

Haskell , 80 bytes

import Data.List
f(x:r)=last$sortOn(0<$)[s|s<-inits=<<tails x,all(isInfixOf s)r]

Experimente online!

Obtenha todos os sufixos ( tails) da primeira palavra xna lista e use todos os prefixos ( inits) desses sufixos para obter todas as substrings sde x. Mantenha cada um sque isInfixOf allcordas na lista restante r. Classifique essas substrings por comprimento (usando o (0<$)truque ) e retorne a última.

Laikoni
fonte
3

Retina 0.8.2 , 48 bytes

M&!`(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)
O#$^`
$.&
1G`

Experimente online! Explicação:

M&!`(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)

Para cada sufixo da primeira sequência, encontre o prefixo mais longo que também é uma substring de todas as outras sequências. Liste todos esses prefixos de sufixo (ou seja, substrings). Se não houver substrings correspondentes, acabamos com a string vazia, que é o que queremos de qualquer maneira.

O#$^`
$.&

Classifique as substrings na ordem inversa do comprimento.

1G`

Mantenha apenas o primeiro, ou seja, o substring mais longo.

Neil
fonte
Let né o número de sequências de argumentos. Então (?=(.*\n.*\1)*.*$)deveria ser (?=(.*\n.*\1){n-1}.*$), não é? Caso de teste:["very", "different", "much"] -> [""]
mazzy 27/03
1
@mazzy Não vejo o problema: experimente online!
Neil
não é um problema. com {n}você, você pode remover os padrões de início e fim e manter (.+)(?=(.*\n.*\1){n}se o Retina permite escrever com nmenos de(?<=^.*).*$
mazzy 27/03
@mazzy Eu não posso no Retina 0.8.2, e no Retina 1 eu teria que mexer com o eval, que provavelmente seria mais longo de qualquer maneira.
Neil
3

Consulta TSQL, 154 bytes

USE master
DECLARE @ table(a varchar(999)collate Latin1_General_CS_AI,i int identity)
INSERT @ values('string'),('stRIng');

SELECT top 1x FROM(SELECT
distinct substring(a,f.number,g.number)x,i
FROM spt_values f,spt_values g,@ WHERE'L'=g.type)D
GROUP BY x ORDER BY-sum(i),-len(x)

Experimente online

Tornou diferenciação de maiúsculas e minúsculas declarando a coluna 'a' com agrupamento contendo CS (diferencia maiúsculas de minúsculas).

Dividindo todas as cadeias de caracteres de 2540 posições iniciais (muitas idênticas), mas os valores úteis variam entre 1 e 2070 e terminando de 0 a 22 caracteres após a posição inicial, a posição final pode ser mais longa alterando o tipo para 'P' em vez de 'L', mas prejudicaria o desempenho.

Essas seqüências distintas em cada número de rown são contadas. A contagem mais alta sempre será igual ao número de linhas na variável da tabela '@'. A reversão da ordem na mesma contagem deixará a substring com a maioria das correspondências por cima dos resultados, seguida pelo comprimento invertido da substring deixará a correspondência mais longa com a maioria das correspondências por cima. A consulta seleciona apenas a primeira linha 1.

Para obter todas as respostas, altere a primeira parte da consulta para

SELECIONE os 1 primeiros com laços x FROM

t-clausen.dk
fonte
3

C # (compilador interativo do Visual C #), 320 257 bytes

l=>(string.Join(",",l.Select(s=>new int[s.Length*s.Length*2].Select((i,j)=>string.Concat(s.Skip(j/-~s.Length).Take(j%-~s.Length))))
.Aggregate((a,b)=>a.Intersect(b)).GroupBy(x=>x.Length).OrderBy(x =>x.Key).LastOrDefault()?.Select(y=>y)??new List<string>()));

Experimente online!

Adereços para @Expired Data e @dana

Innat3
fonte
Você pode simplesmente retornar a string de uma função. Portanto, no compilador interativo, pode ser algo parecido com isto: 294 bytes
Data de
1
Aqui está a solução concentrada em alguns bytes 215 bytes
Data de
@ExpiredData ah perfeito esse é o exemplo que eu precisava :)
Innat3 26/03
186
dana
184
Forma de Ignorância
3

Perl 6 , 62 60 bytes

{~sort(-*.comb,keys [∩] .map(*.comb[^*X.. ^*]>>.join))[0]}

Experimente online!

Estou um pouco chateado porque o Perl 6 não pode fazer operações definidas em listas de listas, e é por isso que há um extra .combe >>lá dentro.

Outra coisa irritante é que maxnão é possível usar uma função para comparar itens, o que significa que eu tenho que usar sort. Como apontado nos comentários, max pode-se usar um argumento, no entanto, acaba sendo mais demorado, pois tenho que levar em conta o maxretorno do infinito negativo quando existem substrings comuns ( tente online! ).

Brincadeira
fonte
3
maxpode assumir essa função (embora a aridade 1), seja pela posição quando chamada no modo OO, seja por um :byargumento nomeado no modo procedural.
Ven
2

Japt v2.0a0 -hF, 8 bytes

Îã f@eøX

Obrigado a Shaggy por salvar 3 bytes

Tente

Îã              //Generate all substrings of the first string
 f@             //Filter; keep the substrings that satisfy the following predicate:
   e            //    If all strings of the input...
    øX          //    Contain this substring, then keep it
-h              //Take last element
-F              //If last element is undefined, default to empty string
Modalidade de ignorância
fonte
Você não precisa classificar por comprimento no final, economizando 3 bytes. Além disso, o -Fpadrão é a sequência vazia.
Shaggy
2

Japonês -h , 8 bytes

(Eu poderia derrubar os últimos 3 bytes e usar a -Fhsinalização, mas não sou fã disso -F)

mã rf iP

Experimente ou execute todos os casos de teste

mã rf iP     :Implicit input of array
m            :Map
 ã           :  Substrings
   r         :Reduce by
    f        :  Filter, keeping only elements that appear in both arrays
      i      :Prepend
       P     :  An empty string
             :Implicit output of last element
Shaggy
fonte
1

Python 3 , 137 bytes

def a(b):c=[[d[f:e]for e in range(len(d)+1)for f in range(e+1)]for d in b];return max([i for i in c[0]if all(i in j for j in c)],key=len)

Experimente online!

Artemis apoia Monica
fonte
Convém usar espaços únicos como recuo em vez de 4 que parecem depilar mais de 100 bytes.
Shieru Asakoto 25/03
@JoKing tio.run/…
Artemis apoia Monica
Certo, aqui está uma versão fixa do programa de 135 bytes
Jo King
1

Python 2 , 103 bytes

lambda b:max(reduce(set.__and__,[{d[f:e]for e in range(len(d)+2)for f in range(e)}for d in b]),key=len)

Experimente online!

Este é um lambda anônimo que transforma cada elemento no conjunto de todas as subseqüências, depois reduceo define intersection ( set.__and__) e, em seguida, retorna o maxelemento por leng.

Brincadeira
fonte
1 byte mais curto com set.intersection.
ovs 25/03
1

Perl 5 ( -aln0777F/\n/ -M5.01 -MList::util=max), 99 bytes

pode ser jogado com mais certeza

map/(.+)(?!.*\1)(?{$h{$&}++})(?!)/,@F;say for grep{y///c==max map y///c,@b}@b=grep@F==$h{$_},keys%h

TIO

Nahuel Fouilleul
fonte
1

JavaScript (ES6),  98  92 bytes

a=>(g=b=s=>a.every(x=>~x.indexOf(s))?b=b[s.length]?b:s:g(s.slice(0,-1,g(s.slice(1)))))(a[0])

Experimente online!

Arnauld
fonte
1

Carvão , 30 bytes

≔⊟θη≔⁰ζFLη«≔✂ηζ⊕ι¹ε¿⬤θ№κεPε≦⊕ζ

Experimente online! Link é a versão detalhada do código. Esse algoritmo é mais eficiente e mais curto do que gerar todas as substrings. Explicação:

≔⊟θη

Coloque a última string da lista de entrada em uma variável.

≔⁰ζ

Zere o índice inicial da substring.

FLη«

Faça um loop sobre todos os possíveis índices finais de substring. (Na verdade, isso passa de 0 excluindo o comprimento, portanto o valor é ajustado posteriormente.)

≔✂ηζ⊕ι¹ε

Obtenha a substring atual.

¿⬤θ№κε

Verifique se esta substring está contida em todas as outras seqüências de entrada.

Pε

Se for, imprimir sobre qualquer substring de saída anterior.

≦⊕ζ

Caso contrário, tente incrementar o índice inicial da substring.

Neil
fonte
1

Bash , 295 .. 175 bytes

Não é bonito, mas pelo menos funciona. Experimente Online

-37 por limpeza geral ; -52 plagiando com a resposta zsh ; -26 substituindo array por um loop ; -2 graças a GammaFunction ; -3 removido i=0do forloop

for l;{ d=${#l}
for((;i<d**2;i++)){ a="${l:i/d:1+i%d}" k=
for n;{ [[ $n =~ $a ]]&&((k++));}
((k-$#))||b+=("$a");};}
for e in "${b[@]}";do((${#e}>${#f}))&&f="$e";done
echo "$f"

Aqui está o script original não destruído, com comentários

roblogic
fonte
1
Economize mais 2: você pode substituir ((k==$#))&&por ((k-$#))||. Isso também permite que você use em k=vez de configurá-lo para 0.
GammaFunction
1
Eu acho que "Não é bonito, mas pelo menos funciona" é o MO para scripts bash :)
joeytwiddle 27/03
0

Vermelho , 266 174 bytes

func[b][l: length? s: b/1 n: 1 until[i: 1 loop n[t: copy/part at s i l r: on foreach u
next b[r: r and(none <> find/case u t)]if r[return t]i: i + 1]n: n + 1 1 > l: l - 1]""]

Experimente online!

Mudou a recursão para a iteração e se livrou da classificação.

Galen Ivanov
fonte
0

JavaScript (Node.js) , 106 bytes

a=>(F=(l,n,w=a[0].substr(n,l))=>l?n<0?F(--l,L-l):a.some(y=>y.indexOf(w)<0)?F(l,n-1):w:"")(L=a[0].length,0)

Experimente online!

a=>(                      // Main function
 F=(                      //  Helper function to run through all substrings in a[0]
  l,                      //   Length
  n,                      //   Start position
  w=a[0].substr(n,l)      //   The substring
 )=>
 l?                       //   If l > 0:
  n<0?                    //    If n < 0:
   F(--l,L-l)             //     Check another length
  :a.some(                //    If n >= 0: 
   y=>y.indexOf(w)<0      //     Check whether there is any string not containing the substring
                          //     (indexOf used because of presence of regex special characters)
  )?                      //     If so:
   F(l,n-1)               //      Check another substring
  :w                      //     If not, return this substring and terminate
                          //     (This function checks from the longest substring possible, so
                          //      it is safe to return right here)
 :""                      //   If l <= 0: Return empty string (no common substring)
)(
 L=a[0].length,           //  Starts from length = the whole length of a[0]
 0                        //  And start position = 0
)
Shieru Asakoto
fonte
0

Gaia , 15 bytes

eḋ¦&⊢⟨:l¦:⌉=¦⟩∇

Experimente online!

e		| eval as code
 ḋ¦		| find all non-empty substrings
   &⊢		| Reduce by set intersection
              ∇	| and return the first element where
      ⟨:l¦:⌉=¦⟩	| the length is equal to the max length
Giuseppe
fonte
0

PowerShell , 165 163 87 bytes

-76 bytes graças a Nail para o incrível regexp .

"$($args-join'
'|sls "(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)"-a -ca|% m*|sort Le*|select -l 1)"

Experimente online!

Menos golfe:

$multilineArgs = $args-join"`n"
$matches = $multilineArgs|sls "(?<=^.*)(.+)(?=(.*\n.*\1)*.*$)" -AllMatches -CaseSensitive|% matches
$longestOrNull = $matches|sort Length|select -Last 1
"$longestOrNull"
confuso
fonte
0

JavaScript (Node.js) , 90 bytes

f=(a,s=e=0,w='')=>a[0][e]?f(a,s+(r=a.some(x=>!x.includes(t),t=a[0].slice(s,++e))),r?w:t):w

Experimente online! Casos de teste roubados descaradamente do @Arnauld. Porto da minha resposta de carvão.

Neil
fonte
0

Java (JDK) , 158 bytes

a->{for(int l=a.get(0).length(),i=l,j;i>=0;i--)for(j=0;j<l-i;){var s=a.get(0).substring(j++,j+i);if(a.stream().allMatch(x->x.contains(s)))return s;}return"";}

Experimente online!

Créditos

  • -17 bytes graças a Sara J .
Olivier Grégoire
fonte
1
159 bytes (casos de teste removidos para ajustar o link do TIO em um comentário)
Sara J
0

Pitão , 16 bytes

eolN.U@bZm{s./dQ

Experimente online!

       m     Q    # Map Q (parsed input) over the following function (lambda d:
          ./d     # Partitions of d (all substrings)
         s        # Reduce on + (make one list)
        {         # deduplicate
    .U            # reduce the result on the following lambda, with starting value result[0]
      @bZ         # lambda b,Z: Intersection between b and Z
                  # Result so far: all common substrings in random order
 o                # sort the resulting sets by the following lambda function:
  lN              # lambda N: len(N)
e                 # last element of that list
ar4093
fonte