Mayor subcadena común


30

Cree un programa o función que tome una lista de cadenas como entrada y genere la cadena más larga que es una subcadena de todas las cadenas de entrada. Si hay varias subcadenas de igual longitud y ya no son más, envíe cualquiera de ellas.

  • Esto puede significar la salida de la cadena vacía.
  • Si hay varias salidas válidas, puede generar cualquiera de ellas. No es necesario que proporcione resultados consistentes para una entrada dada siempre que la salida sea siempre válida.
  • Siempre habrá al menos una cadena en la entrada, pero puede que no haya una cadena no vacía.
  • Todos los caracteres ASCII imprimibles pueden aparecer en la entrada. Puede suponer que esos son los únicos personajes que aparecen.
  • Puede tomar entrada o producir salida por cualquiera de los métodos predeterminados .
  • Las lagunas estándar no están permitidas.
  • Este es el : cuantos menos bytes de código, mejor.

Casos de prueba:

[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"] -> ["&"]


2
@ Adán que pregunta es para el sub común más larga secuencia , no subcadena.
Pomo de la puerta

1
¿Las cadenas serán solo alfanuméricas, alfabéticas o solo para imprimir ascii?
Encarnación de la ignorancia

@EmbodimentofIgnorance Todos los caracteres ASCII imprimibles pueden aparecer en la entrada.
Sara J

2
@ Shaggy Generalmente, no. Si se pueden distinguir los dos, undefinedimplica que no hay una cadena de salida válida. Si la cadena vacía (o cualquier otra cadena) es una salida válida, afirmar que no hay salida válida es incorrecta.
Sara J

Respuestas:


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)

Pruébalo en línea!

Toma entrada salpicada. Tiempo de espera para entradas donde la primera cadena es larga.

La idea es tomar subcadenas de las primeras cadenas hpara encontrar la más larga que aparece en todas las cadenas restantes t. Para hacerlo, recurrimos recursivamente al eliminar el primer o el último carácter 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{''}

Pruébalo en línea!

Un método más directo. La función auxiliar ggenera el conjunto de todas las subcadenas s, y la función principal toma la más larga en su intersección.


8

Brachylog (v2), 3 9 bytes

{sᵛ}ᶠlᵒtw

Pruébalo en línea!

Programa completo Entrada desde entrada estándar (como una lista de cadenas de estilo JSON), salida a salida estándar.

Explicación

{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, el orden de desempate sno es el que está en casi todo lo demás en Brachylog, por lo que debemos anularlo manualmente para producir la salida más larga. (Eso es un poco frustrante: cuatro caracteres adicionales para la anulación, más dos caracteres de agrupación porque Brachylog no analiza dos metapredicados seguidos).

Brachylog's sno devuelve subcadenas vacías, por lo que necesitamos un poco de truco para evitarlo: en lugar de hacer una presentación de función (que es lo que normalmente se hace), escribimos un programa completo, que sale a la salida estándar. De esa manera, si hay una subcadena común, simplemente la sacamos y terminamos. Si no hay una subcadena común, el programa produce errores, pero aún no imprime nada en la salida estándar, por lo tanto, genera la cadena nula como se esperaba.


1
Intenté esto con la entrada ["muchos inpuabts", "any inabputs", "ny iabii", "yanabny"]. Esperaba los resultados ab y ny . Pero solo obtuvo el resultado a . Estoy haciendo algo mal ?
t-clausen.dk

1
Ugh, parece que recordé el orden de desempate por sincorrecto, y anular el orden de desempate es bastante costoso en bytes. Sin embargo, hacer eso ahora de todos modos, porque es importante que la respuesta sea correcta. De alguna manera, ninguno de los casos de prueba que probé notó la diferencia.
ais523

1
@ ais523 El pedido sproduce subcadenas es primero dando todos los prefijos de la entrada (los más largos primero), luego soltando el primero y repitiendo
Kroppeb

5

Jalea , 12 6 bytes

Ẇ€f/ṫ0

Pruébalo en línea!

¡Gracias a @JonathanAllan por guardar 6 bytes!


Creo Ẇ€œ&/Ṫḟ0que haría el trabajo y ahorraría cuatro bytes ya que las subcadenas ya están ordenadas por longitud, por lo tanto, el resultado filtrado será; entonces todo lo que queda es que cuando no hay coincidencias, la cola produce un cero, y dado que tenemos listas de caracteres garantizadas, simplemente podemos filtrarlas.
Jonathan Allan

También creo que œ&/puede ser sustituido por f/aquí ahorro de otra
Jonathan Allan

Envié una solicitud de extracción para (con suerte) hacer que el resultado de reducir una lista vacía sea una lista vacía (en lugar de generar un TypeError). Si eso se fusiona, creo que esta respuesta podría convertirse en un byte de seis Ẇ€f/ṛ/.
Jonathan Allan

@JonathanAllan suena bien. Gracias por los otros consejos, espero que estés feliz de que los haya incorporado.
Nick Kennedy

Sí, mi razón para esos comentarios fue permitirle incorporar las ideas en su publicación.
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]}}}

Pruébalo en línea! - Versión Ruby 2.5 (56 bytes)

¿Cómo?

Cree una lista de posibles coincidencias, inicialmente configurada en la matriz original. Itere en la lista, y si una cadena no coincide, agregue 2 nuevas cadenas a la cola de la lista, cortando el primer o el último carácter. Al final se encontrará una coincidencia (eventualmente una cadena vacía).

Gracias Kirill L por -2 bytes y histocrat por otro -2


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)]

Pruébalo en línea!

Encuentre todas las subcadenas de cada cadena, encuentre la intersección de cada lista de subcadenas, y finalmente devuelva (una de) las más largas.

-3 bytes gracias a Kirill L.

-8 bytes usando en lapply lugar de Map

-2 bytes gracias a Kirill L. nuevamente, quitando llaves


No tengo tiempo para verificarlo, pero si no me equivoco, 2 casos ncharson suficientes para guardar algo al declararme ncharcomo un operador unario.
Kirill L.

@KirillL. Sí, es más corto en 2 bytes. ¡Gracias! Aliasing de listmanera similar nos da -3 bytes.
Giuseppe

También puede soltar llaves para otro -2
Kirill L.

@KirillL. ¡Gracias! Estoy un poco preocupado de comenzar a hacerlo con el código de producción ...
Giuseppe

ese es el problema con jugar al golf en un idioma que usas todos los días
MickyT

4

05AB1E , 14 9 8 bytes

€Œ.«ÃéθJ

-6 bytes gracias a @Adnan .

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

€Œ       # 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)

1
Creo que €Œ.«Ãõªéθdebería funcionar para 9 bytes.
Adnan

@Adnan Espera, tenemos una reducción ... ¿Cómo me perdí eso? : SI lo intentó Å«Ã, pero no me di cuenta de que debería haberlo usado .«Ã. ¡Gracias!
Kevin Cruijssen

1
En realidad, creo que €Œ.«ÃéθJdebería funcionar para 8.
Adnan

4

Zsh , 126 ... 96 bytes

-3 bytes de aritmética para, -6 bytes de implícito "$@"(gracias roblogic), -5 bytes de eliminación innecesaria { }, -1 byte de forma abreviada for, -1 byte usando repeat, -1 byte concatenando for s ($b)con su cuerpo, -13 bytes cambiando el ciclo de repetición para algunos jank eval

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

Pruébalo en línea! Pruébalo en línea! Pruébalo en línea!

Leemos todas las posibles subcadenas en la matriz ay luego establecemos bla intersección de las matrices ay b. La construcción ${b-$a}solo sustituirá $aen la primera iteración: a diferencia de su expansión entre hermanos ${b:-$a}, no sustituirá cuando bse establece sino que está vacía.

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

¿Cómo funciona este bit? a+=( $l[1+i/$#l,1+i%$#l] )
roblogic

1
@roblogic Creo que lo expliqué mejor ahora, verifique la edición. La idea es hacer un bucle a n ^ 2 y usar / y% en lugar de usar 2 forbucles anidados
GammaFunction

1
es posible que pueda cortar for l in "$@"simplemente for l;: es un truco bash
roblogic

Debo decir que zsh es mucho más elegante que bash. No hay nada análogo a esta agradable comparación de matriz AFAIKb=(${${b-$a}:*a})}
roblogic

1
Hay algunas cosas interesantes que puedes hacer con él, y no es tan popular. Eso se traduce en que agrego una respuesta zsh a la mayoría de las preguntas que encuentro. : P Si quieres aprender zsh, te recomiendo man zshexpny man zshparamsobre todo. Siempre los tengo abiertos cuando escribo una respuesta.
GammaFunction

3

Haskell , 80 bytes

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

Pruébalo en línea!

Obtener todos los sufijos ( tails) de la primera palabra xen la lista y tomar todos los prefijos ( inits) de esos sufijos para obtener todas las subcadenas sde x. Mantenga cada uno sque las isInfixOf allcuerdas en la lista restante r. Ordenar esas subcadenas por longitud (usando el (0<$)truco ) y devuelve la última.


3

Retina 0.8.2 , 48 bytes

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

Pruébalo en línea! Explicación:

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

Para cada sufijo de la primera cadena, encuentre el prefijo más largo que también sea una subcadena de todas las otras cadenas. Enumere todos esos prefijos de sufijo (es decir, subcadenas). Si no hay subcadenas coincidentes, simplemente terminamos con la cadena vacía, que es lo que queremos de todos modos.

O#$^`
$.&

Ordenar las subcadenas en orden inverso de longitud.

1G`

Mantenga solo la primera, es decir, la subcadena más larga.


Let nes el número de cadenas de argumentos. Entonces (?=(.*\n.*\1)*.*$)debería ser (?=(.*\n.*\1){n-1}.*$), ¿no? Caso de prueba:["very", "different", "much"] -> [""]
mazzy

1
@mazzy No veo el problema: ¡ Pruébelo en línea!
Neil

No es un problema. con {n}usted podría eliminar los patrones de inicio y finalización y mantenerlos (.+)(?=(.*\n.*\1){n}si Retina permite escribir nmás corto que(?<=^.*).*$
mazzy

@mazzy No puedo en Retina 0.8.2, y en Retina 1 tendría que perder el tiempo con eval, que probablemente sería más largo de todos modos.
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)

Pruébalo en línea

Se distingue entre mayúsculas y minúsculas al declarar la columna 'a' con clasificación que contiene CS (mayúsculas y minúsculas).

Dividiendo todas las cadenas de 2540 posiciones iniciales (muchas idénticas) pero los valores útiles oscilan entre 1 y 2070 y terminando de 0 a 22 caracteres después de la posición inicial, la posición final podría ser más larga cambiando el tipo a 'P' en lugar de 'L', pero paralizaría el rendimiento.

Se cuentan estas cadenas distintas dentro de cada número de rown. El conteo más alto siempre será igual al número de filas en la variable de tabla '@'. Revertir el orden en el mismo recuento dejará la subcadena con la mayoría de las coincidencias en la parte superior de los resultados, seguido de la longitud inversa de la subcadena, dejará la coincidencia más larga con la mayoría de las coincidencias en la parte superior. La consulta solo selecciona la 1 fila superior.

Para obtener todas las respuestas, cambie la primera parte de la consulta a

SELECCIONE la parte superior 1 con lazos x DESDE


3

C # (Visual C # interactivo Compilador), 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>()));

Pruébalo en línea!

Atrezzo a @Expired Data y @dana


Simplemente puede devolver la cadena de una función. Entonces, en el compilador interactivo, podría verse así: 294 bytes
datos

1
Aquí está la solución reducida algunos bytes 215 bytes
Datos

@ExpiredData ah perfecto, este es el ejemplo que necesitaba :)
Innat3



3

Perl 6 , 62 60 bytes

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

Pruébalo en línea!

Estoy un poco molesto porque Perl 6 no puede establecer operaciones en listas de listas, por eso hay un extra .comby >>allí.

Otra cosa molesta es que maxno puede tomar una función de cómo comparar elementos, lo que significa que tengo que usar sorten su lugar. Como se señaló en los comentarios, max puede tomar un argumento, sin embargo, termina más tiempo ya que tengo que tener en cuenta que maxdevuelve el infinito negativo cuando hay subcadenas comunes (¡ Pruébelo en línea! ).


3
maxpuede tomar dicha función (arity 1 sin embargo), ya sea por posición cuando se llama en modo OO, o un :byargumento con nombre en modo de procedimiento.
Ven

2

Japt v2.0a0 -hF, 8 bytes

Îã f@eøX

Gracias a Shaggy por guardar 3 bytes.

Intentalo

Îã              //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

No debería necesitar ordenar por longitud al final, ahorrando 3 bytes. Además, el valor -Fpredeterminado es la cadena vacía.
Shaggy

2

Japt -h , 8 bytes

(Podría eliminar los últimos 3 bytes y usar la -Fhbandera en su lugar, pero no soy fanático de usar -F)

mã rf iP

Pruébalo o ejecuta todos los casos de prueba

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


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)

Pruébalo en línea!

Esta es una lambda anónima que transforma cada elemento en el conjunto de todas las subcadenas, luego reducelo establece mediante la intersección establecida ( set.__and__) y luego devuelve el maxelemento por length.


1 byte más corto con set.intersection.
ovs


1

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

se puede jugar más golf

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

TIO



1

Carbón , 30 bytes

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

Pruébalo en línea! El enlace es a la versión detallada del código. Este algoritmo es más eficiente y más corto que generar todas las subcadenas. Explicación:

≔⊟θη

Haga estallar la última cadena de la lista de entrada en una variable.

≔⁰ζ

Ponga a cero el índice de inicio de la subcadena.

FLη«

Recorra todos los índices finales de subcadenas posibles. (En realidad, esto se repite desde 0 excluyendo la longitud, por lo que el valor se ajusta más adelante)

≔✂ηζ⊕ι¹ε

Obtenga la subcadena actual.

¿⬤θ№κε

Compruebe si esta subcadena está contenida en todas las demás cadenas de entrada.

Pε

Si se sobreimprime cualquier subcadena de salida anterior.

≦⊕ζ

De lo contrario, intente incrementar el índice de inicio de la subcadena.


1

Bash , 295 .. 175 bytes

No es bonito pero al menos funciona. Pruébalo en línea

-37 por limpieza general ; -52 plagiando de la respuesta zsh ; -26 reemplazando la matriz con un bucle ; -2 gracias a GammaFunction ; -3 eliminado i=0del forbucle

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"

Aquí está el guión original sin comentarios con comentarios


1
Ahorre 2 más: puede reemplazar ((k==$#))&&con ((k-$#))||. Esto también le permite usarlo en k=lugar de establecerlo en 0.
GammaFunction

1
Creo que "No es bonito pero al menos funciona" es el MO para los scripts de bash :)
joeytwiddle

0

Rojo , 266174 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]""]

Pruébalo en línea!

Cambió la recursión a iteración y se deshizo de la clasificación.



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)

Pruébalo en línea!

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
)

0

Gaia , 15 bytes

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

Pruébalo en línea!

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

0

PowerShell , 165 163 87 bytes

-76 bytes gracias a Nail por la increíble expresión regular .

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

Pruébalo en línea!

Menos golfizado:

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




0

Pyth , 16 bytes

eolN.U@bZm{s./dQ

Pruébalo en línea!

       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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.