Найбільша поширена підрядка


30

Створіть програму або функцію, яка приймає список рядків як вхідний, і виводить найдовший рядок, який є підрядком всіх вхідних рядків. Якщо є кілька підрядків однакової довжини, і більше немає підрядків, виведіть будь-яку з них.

  • Це може означати виведення порожнього рядка.
  • Якщо є кілька дійсних виходів, ви можете вивести будь-який з них. Вам не потрібно давати послідовний висновок для даного входу до тих пір, поки вихід завжди дійсний.
  • У вході завжди буде хоча б один рядок, але може бути не порожній рядок.
  • Усі друковані символи ASCII можуть відображатися на вході. Ви можете припустити, що це єдині символи, які з'являються.
  • Ви можете взяти введення або отримати вихід будь-яким із методів за замовчуванням .
  • Стандартні лазівки заборонені.
  • Це - чим менше байтів коду, тим краще.

Тестові приклади:

[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 Це запитання задає найдовшу загальну послідовність підрядів , а не підрядку.
Дверна ручка

1
Чи будуть рядки лише буквено-цифровими, або алфавітними, або лише друкованими-ascii?
Втілення Невідомості

@EmbodimentofIgnorance Усі друковані символи ASCII можуть відображатися на вході.
Сара Дж.

2
@Shaggy Загалом, ні. Якщо обидва можна розрізнити, це undefinedозначає, що не існує дійсного вихідного рядка. Якщо порожній рядок (або будь-який інший рядок) є дійсним висновком, стверджуючи, що недійсний висновок є невірним.
Сара Дж

Відповіді:


8

Пітон 2 , 82 байти

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)

Спробуйте в Інтернеті!

Здійснює введення пласкі. Вимкнеться час для входів, де перший рядок довгий.

Ідея полягає в тому, щоб взяти підрядки перших рядків, hщоб знайти найдовшу, що з’являється у всіх решти рядків t. Для цього ми рекурсивно відганяємо на видалення першого або останнього символу h.


Python 2 , 94 байти

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

Спробуйте в Інтернеті!

Більш прямий метод. Допоміжна функція gгенерує безліч всіх підрядків s, а основна функція займає найдовший у їх перетині.


8

Брахілог (v2), 3 9 байт

{sᵛ}ᶠlᵒtw

Спробуйте в Інтернеті!

Повна програма. Введення зі стандартного вводу (як список рядків у стилі JSON), вихід на стандартний вихід.

Пояснення

{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

Судячи з усього, порядок " sтайбрек" - це не те, що є майже у всьому іншому в Брахілозі, тому нам потрібно вручну змінити його, щоб отримати найдовший вихід. (Це трохи засмучує: чотири зайвих символи для переопрацювання, плюс два символи групування, оскільки Брахілог не розбирає двох метапредметів підряд.)

Брахілог sне повертає порожні підрядки, тому нам потрібен трохи хитрість, щоб обійти це: замість того, щоб зробити подання функції (що зазвичай робиться), ми пишемо повну програму, виводимо на стандартний вихід. Таким чином, якщо є загальна підрядка, ми просто виводимо її, і ми закінчуємо. Якщо немає загальної підрядки, програма помиляється - але вона все одно нічого не друкує до стандартного виводу, таким чином виводить нульову рядок за призначенням.


1
Я спробував це з введенням ["багато inpuabts", "any inabputs", "ny iabii", "yanabny"]. Я очікував результатів ab і ny . Але отримав лише результат а . Я щось роблю не так?
t-clausen.dk

1
Фу, здається, я пам'ятав, що порядок тайбрек був sневірним, і переосмислення порядку набору було досить дорогим. Але все одно це робити, бо важливо, щоб відповідь була правильною. Якось у жодному з тестових випадків я не намагався помітити різницю.
ais523

1
@ ais523 Порядок sстворює підрядки - це спочатку даючи всі префікси вводу (найдовше спочатку), потім відкидаючи перший і повторюючи
Кроппеб

5

Желе , 12 6 байт

Ẇ€f/ṫ0

Спробуйте в Інтернеті!

Дякуємо @JonathanAllan за збереження 6 байт!


Я вважаю, що Ẇ€œ&/Ṫḟ0це зробить роботу і збереже чотири байти, оскільки підрядки вже впорядковані по довжині, отже, відфільтрований результат буде; то залишається лише те, що коли немає збігів, хвіст створює нуль, і оскільки у нас є гарантійні списки символів, ми можемо їх просто відфільтрувати.
Джонатан Аллан

Також я думаю, що тут œ&/може бути замінено f/економію іншого
Джонатана Аллана

Я подав запит на витяг, щоб (сподіваюсь) зробити результат зменшення порожнього списку порожнім списком (а не підвищувати TypeError). Якщо це об'єднається, я вважаю, що ця відповідь може стати шестибайтовою Ẇ€f/ṛ/.
Джонатан Аллан

@JonathanAllan звучить добре. Дякуємо за інші поради - сподіваюся, ви були щасливі, що я включив їх.
Нік Кеннеді

Так, мої причини для цих коментарів полягали в тому, щоб ви могли включити ідеї у свій пост.
Джонатан Аллан

5

Ruby 2.6, 76 59 54 байт

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

Спробуйте в Інтернеті! - версія Ruby 2.5 (56 байт)

Як?

Створіть список потенційних відповідностей, спочатку встановлений у вихідному масиві. Повторіть список, і якщо рядок не збігається, додайте 2 нові рядки до хвоста списку, відсікаючи перший або останній символ. Наприкінці буде знайдено збіг (зрештою порожній рядок).

Дякую Кирилу Л за -2 байти, а гістотору ще -2


4

R , 119 116 108 106 байт

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

Спробуйте в Інтернеті!

Знайдіть усі підрядки кожного рядка, знайдіть перетин кожного списку підрядів, а потім нарешті поверніть (одну з) найдовшу.

-3 байти завдяки Кирилу Л.

-8 байт, використовуючи lapply замість Map

-2 байти завдяки Кирилу Л. знову, знявши брекети


Я не встигаю перевірити, але якщо я не помиляюсь, ncharдостатньо двох випадків , щоб щось врятувати, оголосивши ncharсебе одинарним оператором.
Кирило Л.

@KirillL. так, він коротший на 2 байти. Спасибі! Згладжування listаналогічно дає нам -3 байти.
Джузеппе

Ви також можете скинути брекети на ще -2
Кирилл Л.

@KirillL. Спасибі! Я трохи переживаю, що почну робити це з виробничим кодом ...
Джузеппе

ось проблема з гольфом мовою, якою ви користуєтесь щодня
MickyT

4

05AB1E , 14 9 8 байт

€Œ.«ÃéθJ

-6 байт завдяки @Adnan .

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

€Œ       # 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
Думаю, €Œ.«Ãõªéθслід працювати на 9 байт.
Аднан

@Adnan Почекайте, у нас зменшення. Як я це пропустив. : SI спробував Å«Ã, але не зрозумів, що я повинен був використовувати це .«Ãзамість .. Дякую!
Кевін Круїссен

1
Насправді, я думаю, €Œ.«ÃéθJмає працювати для 8.
Аднан

4

Zsh , 126 ... 96 байт

-3 байти з арифметики за, -6 байт з неявного "$@"(спасибі рологічного), -5 байт з видалення непотрібного { }, -1 байт із короткої форми for, -1 байт за допомогою repeat, -1 байт шляхом об'єднання for s ($b)з його тілом, -13 байт змінивши цикл повторення для деяких eval jank.

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

Спробуйте в Інтернеті! Спробуйте в Інтернеті! Спробуйте в Інтернеті!

Ми читаємо всі можливі підрядки в масив a, а потім встановлюємо bна перетин масивів aі b. Конструкція ${b-$a}буде заміщати лише $aпід час першої ітерації: на відміну від свого розширення ${b:-$a}, він не замінить, коли bвстановлено, а порожній.

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

Як працює цей біт? a+=( $l[1+i/$#l,1+i%$#l] )
roblogic

1
@roblogic Я думаю, що я пояснив це краще зараз, перевірте правки. Ідея полягає у циклі на n ^ 2 та використанні / і% замість використання 2 вкладених forциклів
GammaFunction

1
можливо, ви зможете вирізати for l in "$@"просто for l;- це баш-трюк
roblogic

Треба сказати, zsh настільки елегантніше, ніж баш. Нічого подібного до цього приємного порівняння масиву AFAIKb=(${${b-$a}:*a})}
roblogic

1
Можна зробити кілька акуратних речей, і це не все так популярно. Це означає, що я додаю zsh відповіді на більшість питань, на які я стикаюся. : P Якщо ви хочете вивчити zsh, рекомендую man zshexpnі man zshparamособливо. Я завжди відкриваю їх під час написання відповіді.
GammaFunction

3

Хаскелл , 80 байт

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

Спробуйте в Інтернеті!

Отримати всі суфікси ( tails) першого слова xв списку і вжити всіх префікси ( inits) з цих суфіксів , щоб отримати всі підрядка sз x. Тримайте кожен , sщо isInfixOf allрядки в останньому списку r. Сортувати ці підрядка по довжині ( з використанням в (0<$)трик ) і повернути останній.


3

Сітківка 0,8,2 , 48 байт

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

Спробуйте в Інтернеті! Пояснення:

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

Для кожного суфікса першого рядка знайдіть найдовший префікс, який також є підрядком для всіх інших рядків. Перерахуйте всі ці суфіксні префікси (тобто підрядки). Якщо немає відповідних підрядків, ми просто закінчуємо порожній рядок, який ми все одно хочемо.

O#$^`
$.&

Сортуйте підрядки у зворотному порядку за довжиною.

1G`

Зберігайте лише першу, тобто найдовшу підрядку.


Let n- це кількість рядків аргументів. Тоді (?=(.*\n.*\1)*.*$)має бути (?=(.*\n.*\1){n-1}.*$), чи не так? Тестовий випадок:["very", "different", "much"] -> [""]
mazzy

1
@mazzy Я не бачу проблеми: Спробуйте в Інтернеті!
Ніл

це не проблема. з {n}ви можете видалити шаблони початку і кінця і зберегти , (.+)(?=(.*\n.*\1){n}якщо Retina дозволяє писати nкоротше(?<=^.*).*$
Mazzy

@mazzy Я не можу в Retina 0.8.2, а в Retina 1 мені доведеться возитися з eval, що, мабуть, все одно буде довше.
Ніл

3

Запит TSQL, 154 байти

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)

Спробуйте в Інтернеті

Зрозуміло регістр, оголосивши стовпець "a" зіставленням, що містить CS (регістр).

Розбиваючи всі рядки з 2540 початкових позицій (багато однакових), але корисні значення варіюються між 1 і 2070 і закінчуються від 0 до 22 символів після вихідної позиції, кінцева позиція може бути довшою, змінивши тип на "P" замість "L", але зробить калікою продуктивність.

Ці чіткі рядки в кожному рядовому номері рахуються. Найвища кількість завжди буде дорівнює кількості рядків у змінній таблиці "@". Якщо змінити порядок на один і той же підрахунок, то підрядок залишиться з більшістю збігів на вершині результатів, після чого перевернута довжина підрядка залишить найдовший збіг з більшістю збігів зверху. Запит вибирає лише верхній 1 рядок.

Щоб отримати всі відповіді, змініть першу частину запиту на

ВИБІРТЕ верхній 1з краватками х ВІД


3

C # (Visual C # Interactive Compiler), 320 257 байт

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

Спробуйте в Інтернеті!

Реквізити для @Expired Data і @dana


Ви можете просто повернути рядок з функції. Тож у інтерактивному компіляторі це може виглядати приблизно так: 294 байти
Термін дії даних закінчився

1
Ось рішення, набране на кілька байт 215 байт
Термін дії закінчився

@ExpiredData ах ідеально, це приклад, який мені знадобився :)
Innat3



3

Perl 6 , 62 60 байт

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

Спробуйте в Інтернеті!

Я трохи роздратований, Perl 6 не може робити операції зі списків списків, тому там є додатковий .combі >>там.

Інша дратівлива річ полягає в тому, що я maxне можу скористатися функцією порівняння предметів, тобто я повинен використовувати її sortзамість. Як зазначалося в коментарях, max можна взяти аргумент, однак він закінчується довше, оскільки я повинен враховувати maxповернення негативної нескінченності, коли є загальні підрядки ( Спробуйте це в Інтернеті! ).


3
maxможе приймати таку функцію (хоча паралельність 1), або за позицією, коли викликається в режимі OO, або іменованим :byаргументом у процедурному режимі.
Ven

2

Japt v2.0a0 -hF, 8 байт

Îã f@eøX

Завдяки Shaggy за збереження 3 байтів

Спробуй це

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

Вам не потрібно буде сортувати за довжиною в кінці, економлячи 3 байти. Також -Fза замовчуванням до порожнього рядка.
Кудлатий

2

Japt -h , 8 байт

(Я міг би зняти останні 3 байти і використовувати -Fhпрапор замість цього, але я не прихильник використання -F)

mã rf iP

Спробуйте або запустіть усі тестові приклади

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

Пітон 3 , 137 байт

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)

Спробуйте в Інтернеті!


Ви можете використовувати окремі пробіли як відступи замість 4, які, здається, голити більше 100 байт.
Шиеру Асакото


Ось, ось виправлена ​​версія 135-байтної програми
Джо Кінг,

1

Python 2 , 103 байти

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)

Спробуйте в Інтернеті!

Це анонімна лямбда, яка перетворює кожен елемент у набір усіх підрядків, потім reduces його шляхом встановлення перетину ( set.__and__), а потім повертає maxелемент length.


1 байт коротше , з set.intersection.
ов


1

Perl 5 ( -aln0777F/\n/ -M5.01 -MList::util=max), 99 байт

може бути гольф, звичайно

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

ТІО



1

Вугілля деревне , 30 байт

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Цей алгоритм більш ефективний і коротший, ніж генерування всіх підрядків. Пояснення:

≔⊟θη

Перемістіть останній рядок зі списку вхідних даних у змінну.

≔⁰ζ

Нульовий показник запуску підрядки.

FLη«

Переведіть петлю на всі можливі індекси кінцевих рядків. (Насправді це циклі від 0, виключаючи довжину, тому значення коригується пізніше.)

≔✂ηζ⊕ι¹ε

Отримайте поточну підрядку.

¿⬤θ№κε

Перевірте, чи міститься ця підрядка у всіх інших вхідних рядках.

Pε

Якщо це, то надрукуйте будь-яку раніше вихідну підрядку.

≦⊕ζ

В іншому випадку спробуйте збільшити індекс запуску підрядки.


1

Баш , 295 .. 175 байт

Не дуже, але принаймні це працює. Спробуйте в Інтернеті

-37 загальним прибиранням ; -52 шляхом плагіатування з відповіді zsh ; -26 шляхом заміни масиву циклом ; -2 завдяки GammaFunction ; -3 зняти i=0з forпетлі

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"

Ось оригінальний сценарій без вогків із коментарями


1
Збережіть ще 2: Ви можете замінити ((k==$#))&&на ((k-$#))||. Це також дозволяє вам використовувати k=замість того, щоб встановити його на 0.
GammaFunction

1
Я думаю, що "Не дуже, але принаймні це працює" є МО для баш сценаріїв :)
joeytwiddle



0

JavaScript (Node.js) , 106 байт

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)

Спробуйте в Інтернеті!

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

PowerShell , 165 163 87 байт

-76 байт завдяки нігтям за приголомшливий регулярний вираз .

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

Спробуйте в Інтернеті!

Менше гольфу:

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




0

Pyth , 16 байт

eolN.U@bZm{s./dQ

Спробуйте в Інтернеті!

       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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.