Massima sottostringa comune


30

Creare un programma o una funzione che accetta un elenco di stringhe come input e genera la stringa più lunga che è una sottostringa di tutte le stringhe di input. Se sono presenti più sottostringhe di uguale lunghezza e non più sottostringa, emetterne una qualsiasi.

  • Ciò può significare emettere la stringa vuota.
  • Se sono presenti più output validi, è possibile emetterne uno qualsiasi. Non è necessario fornire un output coerente per un determinato input, purché l'output sia sempre valido.
  • Ci sarà sempre almeno una stringa nell'input, ma potrebbe non esserci una stringa non vuota.
  • Tutti i caratteri ASCII stampabili possono apparire nell'input. Puoi presumere che questi siano gli unici personaggi che appaiono.
  • È possibile accettare input o produrre output con uno dei metodi predefiniti .
  • Non sono ammesse scappatoie standard .
  • Questo è - meno byte di codice, meglio è.

Casi test:

[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ám Tale questione chiede la più lunga comuni sub sequenza , non sottostringa.
Maniglia della porta

1
Le stringhe saranno solo alfanumeriche o alfabetiche o solo stampabili-ascii?
Incarnazione dell'ignoranza il

@EmbodimentofIgnorance Tutti i caratteri ASCII stampabili possono apparire nell'input.
Sara J

2
@Shaggy In generale, no. Se i due possono essere distinti, undefinedimplica che non esiste una stringa di output valida. Se la stringa vuota (o qualsiasi altra stringa) è un output valido, affermare che non esiste un output valido non è corretto.
Sara J

Risposte:


8

Python 2 , 82 byte

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)

Provalo online!

Accetta input splattato. Timeout per input in cui la prima stringa è lunga.

L'idea è quella di prendere sottostringhe delle prime stringhe hper trovare la più lunga che appare in tutte le stringhe rimanenti t. Per fare ciò, ricorsivamente ricamiamo sulla rimozione del primo o dell'ultimo carattere di h.


Python 2 , 94 byte

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

Provalo online!

Un metodo più diretto. La funzione ausiliaria ggenera l'insieme di tutte le sottostringhe di s, e la funzione principale prende quella più lunga nella loro intersezione.


8

Brachylog (v2), 3 9 byte

{sᵛ}ᶠlᵒtw

Provalo online!

Programma completo. Input da input standard (come un elenco di stringhe in stile JSON), output in output standard.

Spiegazione

{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

Apparentemente, l'ordine del tiebreak snon è quello che è in quasi tutto il resto in Brachylog, quindi abbiamo bisogno di sovrascriverlo manualmente per produrre l'output più lungo. (È un po 'frustrante: quattro personaggi extra per l'override, più due personaggi di raggruppamento perché Brachylog non analizza due metapredicati di fila.)

Brachylog snon restituisce sottostringhe vuote, quindi abbiamo bisogno di un po 'di trucco per aggirare questo: invece di inviare una funzione (che è ciò che è normalmente fatto), scriviamo un programma completo, producendo output standard. In questo modo, se esiste una sottostringa comune, la produciamo e abbiamo finito. Se non esiste una sottostringa comune, il programma si guasta, ma non stampa ancora nulla sull'output standard, quindi restituisce la stringa nulla come previsto.


1
Ho provato questo con l'input ["many inpuabts", "any inabputs", "ny iabii", "yanabny"]. Mi aspettavo i risultati ab e ny . Ma ho ottenuto solo il risultato a . Sto facendo qualcosa di sbagliato ?
t-clausen.dk il

1
Ugh, sembra che mi sia ricordato l'ordine del tiebreak per serrore, e ignorare l'ordine del tiebreak è piuttosto costoso in termini di byte. Fallo ora comunque, comunque, perché è importante che la risposta sia corretta. In qualche modo nessuno dei casi di test che ho provato ha notato la differenza.
ais523

1
@ ais523 L'ordine sproduce sottostringhe dando prima tutti i prefissi dell'input (prima il più lungo), quindi rilasciando il primo e ripetendo
Kroppeb

5

Gelatina , 12 6 byte

Ẇ€f/ṫ0

Provalo online!

Grazie a @JonathanAllan per aver salvato 6 byte!


Credo che Ẇ€œ&/Ṫḟ0farebbe il lavoro e risparmierebbe quattro byte poiché le sottostringhe sono già ordinate per lunghezza, quindi il risultato filtrato sarà; allora tutto ciò che rimane è che quando non ci sono corrispondenze la coda produce uno zero, e poiché siamo garantiti elenchi di caratteri possiamo semplicemente filtrarli.
Jonathan Allan il

inoltre penso che œ&/possa essere sostituito f/qui salvandone un altro
Jonathan Allan il

Ho inviato una richiesta pull per (si spera) rendere il risultato della riduzione di un elenco vuoto sia un elenco vuoto (piuttosto che sollevare un TypeError). Se questo si fonde, credo che questa risposta potrebbe diventare una scocciatura Ẇ€f/ṛ/.
Jonathan Allan,

@JonathanAllan suona bene. Grazie per gli altri suggerimenti - spero che tu fossi felice per me incorporarli.
Nick Kennedy il

Sì, la mia ragione per quei commenti era di permetterti di incorporare le idee nel tuo post.
Jonathan Allan,

5

Ruby 2.6, 76 59 54 byte

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

Provalo online! - Versione Ruby 2.5 (56 byte)

Come?

Crea un elenco di potenziali corrispondenze, inizialmente impostato sull'array originale. Scorri nell'elenco e, se una stringa non corrisponde, aggiungi 2 nuove stringhe alla coda dell'elenco, tagliando il primo o l'ultimo carattere. Alla fine verrà trovata una corrispondenza (eventualmente una stringa vuota).

Grazie Kirill L per -2 byte e istocratico per un altro -2


4

R , 119 116 108 106 byte

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

Provalo online!

Trova tutte le sottostringhe di ogni stringa, trova l'intersezione di ogni elenco di sottostringhe, quindi restituisce (una delle) più lunghe.

-3 byte grazie a Kirill L.

-8 byte usando lapply invece di Map

-2 byte grazie ancora a Kirill L., rimuovendo le parentesi graffe


Non ho tempo di controllare, ma se non sbaglio, 2 occorrenze di ncharsono sufficienti per salvare qualcosa dichiarando ncharun operatore unario.
Kirill L.

@KirillL. sì, è più breve di 2 byte. Grazie! Alloiasing in listmodo simile ci dà -3 byte.
Giuseppe

Puoi anche rilasciare le parentesi graffe per un altro -2
Kirill L.

@KirillL. Grazie! Sono un po 'preoccupato che inizierò a farlo con il codice di produzione ...
Giuseppe,

questo è il problema con il golf una lingua che usi tutti i giorni
MickyT

4

05AB1E , 14 9 8 byte

€Œ.«ÃéθJ

-6 byte grazie a @Adnan .

Provalo online o verifica tutti i casi di test .

Spiegazione:

€Œ       # 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
Penso che €Œ.«Ãõªéθdovrebbe funzionare per 9 byte.
Adnan,

@Adnan Aspetta, abbiamo una riduzione .. Come mi sono perso. : Å«ÃCi ho provato , ma non avevo capito che avrei dovuto usare .«Ãinvece .. Grazie!
Kevin Cruijssen,

1
In realtà, penso che €Œ.«ÃéθJdovrebbe funzionare per 8.
Adnan il

4

Zsh , 126 ... 96 byte

-3 byte dall'aritmetica per, -6 byte dall'implicito "$@"(grazie roblogic), -5 byte dalla rimozione non necessaria { }, -1 byte dalla forma breve di for, -1 byte usando repeat, -1 byte concatenando for s ($b)con il suo corpo, -13 byte cambiando il loop di ripetizione per qualche jank eval.

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

Provalo online! Provalo online! Provalo online!

Leggiamo tutte le sottostringhe possibili nell'array ae quindi impostiamo bl'intersezione degli array ae b. Il costrutto ${b-$a}sostituirà solo $ala prima iterazione: a differenza della sua espansione fratello ${b:-$a}, non sostituirà quando bè impostato ma vuoto.

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

Come funziona questo bit? a+=( $l[1+i/$#l,1+i%$#l] )
roblogic

1
@roblogic Penso di averlo spiegato meglio ora, controlla la modifica. L'idea è di eseguire il loop su n ^ 2 e utilizzare / e% invece di utilizzare 2 forloop nidificati
GammaFunction

1
potresti essere in grado di tagliare for l in "$@"semplicemente for l;- è un trucco bash
roblogic

devo dire che zsh è molto più elegante di bash. Non c'è nulla di analogo a questo bel confronto di array AFAIKb=(${${b-$a}:*a})}
roblogic

1
Ci sono alcune cose belle che puoi fare con esso, e non è poi così popolare. Ciò si traduce in me aggiungendo una risposta zsh alla maggior parte delle domande che incontro. : P Se vuoi imparare zsh, lo consiglio man zshexpne man zshparamsoprattutto. Li ho sempre aperti quando si scrive una risposta.
Funzione gamma

3

Haskell , 80 byte

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

Provalo online!

Prendi tutti i suffissi ( tails) della prima parola xnell'elenco e prendi tutti i prefissi ( inits) di quei suffissi per ottenere tutte le sottostringhe sdi x. Mantenere ogni sche isInfixOf allle stringhe nella lista restante r. Ordina quelle sottostringhe per lunghezza (usando il (0<$)trucco ) e restituisci l'ultima.


3

Retina 0.8.2 , 48 byte

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

Provalo online! Spiegazione:

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

Per ogni suffisso della prima stringa, trova il prefisso più lungo che è anche una sottostringa di tutte le altre stringhe. Elenca tutti quei prefissi di suffisso (ovvero sottostringhe). Se non ci sono sottostringhe corrispondenti, finiamo con la stringa vuota, che è comunque ciò che vogliamo.

O#$^`
$.&

Ordinare le sottostringhe in ordine inverso di lunghezza.

1G`

Mantenere solo il primo, ovvero la sottostringa più lunga.


Let nè il numero di stringhe di argomenti. Quindi (?=(.*\n.*\1)*.*$)dovrebbe essere (?=(.*\n.*\1){n-1}.*$), no? Caso di prova:["very", "different", "much"] -> [""]
mazzy

1
@mazzy Non vedo il problema: provalo online!
Neil

non è un problema. con {n}te potresti rimuovere gli schemi di inizio e fine e continuare (.+)(?=(.*\n.*\1){n}se Retina permette di scrivere npiù breve di(?<=^.*).*$
mazzy il

@mazzy Non riesco a Retina 0.8.2, e in Retina 1 dovrei scherzare con eval, che probabilmente sarebbe più lungo comunque.
Neil

3

Query TSQL, 154 byte

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)

Provalo online

Rendi maiuscole e minuscole dichiarando la colonna 'a' con regole di confronto contenenti CS (case sensitive).

Dividendo tutte le stringhe da 2540 posizioni iniziali (molte identiche) ma i valori utili vanno da 1 a 2070 e terminano da 0 a 22 caratteri dopo la posizione iniziale, la posizione finale potrebbe essere più lunga cambiando il tipo in 'P' invece di 'L', ma paralizzerebbe le prestazioni.

Vengono contate queste stringhe distinte all'interno di ciascun rownumber. Il conteggio più alto sarà sempre uguale al numero di righe nella variabile di tabella '@'. L'inversione dell'ordine sullo stesso conteggio lascerà la sottostringa con la maggior parte delle corrispondenze in cima ai risultati seguita da una lunghezza inversa della sottostringa lascerà la corrispondenza più lunga con la maggior parte delle corrispondenze in cima. La query seleziona solo la prima riga in alto.

Per ottenere tutte le risposte, modificare la prima parte della query in

SELEZIONA in alto 1 con legami x DA


3

C # (compilatore interattivo Visual C #), 320 257 byte

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>()));

Provalo online!

Puntelli a @Expired Data e @dana


Puoi semplicemente restituire la stringa da una funzione. Quindi nel compilatore interattivo potrebbe essere simile a questo: 294 byte
Dati scaduti il

1
Ecco la soluzione che ha raggiunto alcuni byte 215 byte
Dati scaduti il

@ExpiredData ah perfetto questo è l'esempio di cui avevo bisogno :)
Innat3



3

Perl 6 , 62 60 byte

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

Provalo online!

Sono un po 'seccato che Perl 6 non riesca a fare operazioni su elenchi di elenchi, motivo per cui c'è un extra .combe >>lì dentro.

Un'altra cosa fastidiosa è che maxnon può assumere una funzione su come confrontare gli oggetti, il che significa che devo usare sortinvece. Come sottolineato nei commenti, max può prendere un argomento, ma finisce più a lungo poiché devo tenere conto del maxritorno dell'infinito negativo quando ci sono sottostringhe comuni ( Provalo online! ).


3
maxpuò assumere tale funzione (arity 1 però), sia per posizione quando chiamato in modalità OO, sia per un :byargomento denominato in modalità procedurale.
Ven

2

Japt v2.0a0 -hF, 8 byte

Îã f@eøX

Grazie a Shaggy per aver salvato 3 byte

Provalo

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

Non dovresti aver bisogno di ordinare per lunghezza alla fine, risparmiando 3 byte. Inoltre, per -Fimpostazione predefinita è la stringa vuota.
Shaggy

2

Japt -h , 8 byte

(Potrei eliminare gli ultimi 3 byte e usare -Fhinvece la bandiera ma non sono un fan dell'uso -F)

mã rf iP

Provalo o esegui tutti i casi di test

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 byte

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)

Provalo online!

Si tratta di una lambda anonima che trasforma ogni elemento nell'insieme di tutte le sottostringhe, quindi reduceviene impostato per intersezione (set.__and__ ) e quindi restituisce l' maxelemento per length.


1 byte più corto con set.intersection.
Ovs


1

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

può essere giocato a golf più certamente

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

TIO


1

JavaScript (ES6),  98  92 byte

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

Provalo online!


1

Carbone , 30 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Questo algoritmo è più efficiente e più breve rispetto alla generazione di tutte le sottostringhe. Spiegazione:

≔⊟θη

Pop l'ultima stringa dall'elenco di input in una variabile.

≔⁰ζ

Azzerare l'indice iniziale della sottostringa.

FLη«

Passa sopra tutti i possibili indici di estremità della sottostringa. (In realtà questo passa da 0 escludendo la lunghezza, quindi il valore viene regolato in seguito.)

≔✂ηζ⊕ι¹ε

Ottieni la sottostringa corrente.

¿⬤θ№κε

Controllare se questa sottostringa è contenuta in tutte le altre stringhe di input.

Pε

Se viene quindi sovrastampato qualsiasi sottostringa di output precedente.

≦⊕ζ

In caso contrario, provare ad aumentare l'indice di avvio della sottostringa.


1

Bash , 295 .. 175 byte

Non carino ma almeno funziona. Provalo online

-37 per pulizia generale ; -52 plagiando dalla risposta zsh ; -26 sostituendo l'array con un loop ; -2 grazie a GammaFunction ; -3 rimosso i=0dal 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"

Ecco la sceneggiatura originale non scritta con commenti


1
Salva altri 2: puoi sostituirlo ((k==$#))&&con ((k-$#))||. Questo ti permette anche di usarlo k=invece di impostarlo su 0.
GammaFunction

1
Penso che "Non carino ma almeno funziona" è il MO per gli script bash :)
joeytwiddle,

0

Rosso , 266 174 byte

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

Provalo online!

Modificata la ricorsione in iterazione e eliminato lo smistamento.



0

JavaScript (Node.js) , 106 byte

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)

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

0

Gaia , 15 byte

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

Provalo 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

0

PowerShell , 165 163 87 byte

-76 byte grazie a Nail per l' impressionante regexp .

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

Provalo online!

Meno golf:

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

0

JavaScript (Node.js) , 90 byte

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

Provalo online! Casi di test spudoratamente rubati da @Arnauld. Porto della mia risposta al carbone.




0

Pyth , 16 byte

eolN.U@bZm{s./dQ

Provalo 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.