Найкоротший довгий загальний наступний код


11

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

Дійсне вирішення проблеми ЛГП для двох або більше рядків S 1 , ... S п будь-який рядок T максимальної довжини, що характери Т з'являються у всіх S I , в тому ж порядку , як і в T .

Зверніть увагу , що T не повинен бути суб рядок з S я .

Приклад

Рядки axbyczі xaybzcмають 8 загальних підпослідовності довжини 3:

abc abz ayc ayz xbc xbz xyc xyz

Будь-яке з них було б вагомим рішенням проблеми LCS.

Деталі

Напишіть програму або функцію, яка вирішує проблему LCS, як пояснено вище, дотримуючись наступних правил:

  • Вхід складається з двох або більше рядків, що містять лише малі літери.

    Ви можете прочитати ці рядки як масив рядків або окремий рядок із роздільником, який ви обрали.

  • Ваш код повинен виводити будь-яке одне з можливих варіантів вирішення проблеми, необов'язково супроводжуючись подачею рядків або оточеним цитатами.

  • Ви можете припустити, що рядки коротші 1000 символів і щонайменше 20 рядків.

    У цих межах ваш код повинен працювати як слід теоретично (з урахуванням необмеженого часу та пам'яті).

  • Ваш код повинен заповнити комбіновані тестові випадки наступного розділу протягом менш ніж години на моїй машині (Intel Core i7-3770, 16 Гб оперативної пам’яті).

    Підходи, які просто повторюють усі можливі подальші підходи, не будуть відповідати часовому обмеженню.

  • Використання вбудованих модулів, які тривілізують це завдання, наприклад LongestCommonSequence, заборонено.

Діють стандартні правила .

Тестові справи

a
ab

Вихід: a


aaaaxbbbb
bbbbxcccc
ccccxaaaa

Вихід: x


hxbecqibzpyqhosszypghkdddykjfjcajnwfmtfhqcpavqrtoipocijrmqpgzoufkjkyurczxuhkcpehbhpsuieqgjcepuhbpronmlrcgvipvibhuyqndbjbrrzpqbdegmqgjliclcgahxoouqxqpujsyfwbdthteidvigudsuoznykkzskspjufgkhaxorbrdvgodlb
qnnprxqpnafnhekcxljyysobbpyhynvolgtrntqtjpxpchqwgtkpxxvmwwcohxplsailheuzhkbtayvmxnttycdkbdvryjkfhshulptkuarqwuidrnjsydftsyhuueebnrjvkfvhqmyrclehcwethsqzcyfvyohzskvgttggndmdvdgollryqoswviqurrqhiqrqtyrl

Вихід: hxbbpyhogntqppcqgkxchpsieuhbncvpuqndbjqmclchqyfttdvgoysuhrrlабо будь-яке інше спільне підряд однакової довжини


riikscwpvsbxrvkpymvbbpmwclizxlhihiubycxmxwviuajdzoonjpkgiuiulbjdpkztsqznhbjhymwzkutmkkkhirryabricvhb
jnrzutfnbqhbaueicsvltalvqoorafnadevojjcsnlftoskhntashydksoheydbeuwlswdzivxnvcrxbgxmquvdnfairsppodznm
kzimnldhqklxyezcuyjaiasaeslicegmnwfavllanoolkhvqkjdvxrsjapqqwnrplcwqginwinktxnkfcuuvoyntrqwwucarfvjg

Вихід: icsvllvjnlktywuarабо будь-яке інше спільне підряд однакової довжини


rblartqkfggrjpiipuzzypkycnyckkcqceeujiyy
yfpnedyjtiwrhyuktripdwyvgkblzodeufkelhub
ywcyboxwqkibwvredkrbdsyudkulpvmhixeqxynh
bnxwahbzhwjxkotnvbxrojkkldtsodtjmvdrmbgr

Вихід: krkkабо будь-яке інше спільне підряд однакової довжини


bwfscmotshoczmduwaev
coywaaizdaxjovipsmeh
dobzcpoiedenzlfdjpiu
bbhfeqscvvbwkuoxdoge
drqrzwbcpcsvneodelja

Вихід: codeабо будь-яке інше спільне підряд однакової довжини


nqrualgoedlf
jgqorzglfnpa
fgttvnogldfx
pgostsulyfug
sgnhoyjlnfvr
wdttgkolfkbt

Вихід: golfабо будь-яке інше спільне підряд однакової довжини


epopyfuhgowedpiqpgfj
ddxyestqynpwmytxhozm
ptubgzyqqksieoovuezv
tovotqmnhgzttfpywjgr
aomvytkgaijlgqzkljls
vzvxpaixrnprxvenbbuo
syfuwxlpcyontqlmfvib
arxleuomstkjegpduwcx
xgqrxaopouvkvwgbzewn
yggunddigctgpnuztzai
izroomywwztdymqszsuo
kiawjnxjncdtufhkrjsp

Вихід: порожній рядок



@NotthatCharles Не всі. Це запитання дає лише два рядки як вхідні дані та не має обмежень за часом. Усі існуючі відповіді використовують наївні підходи, які надто повільні, щоб відповідати правилам цього питання.
Денніс

Останній приклад, ймовірно, займає найдовший час для обчислення, проте спочатку видаляючи кожен символ, який не відображається у кожній рядку, тривіально виводити порожній рядок. Чи можете ви додати ще один приклад з однаковою кількістю рядків і довжиною рядків, де кожен використаний символ відображається в кожній рядку і де LCS має щонайменше 5 символів або близько того? Щось на кшталт: ghostbin.com/paste/x9caq
Тайло

@Tylio Включення певної логіки, яка закінчує рекурсію на ранніх етапах, якщо рядки не мають більше загальних символів, майже все, що стосується останнього тестового випадку.
Денніс

@Dennis Отже, рішення не повинно працювати в розумний час з 20 довільною довжиною 1000 рядків?
Тіїло

Відповіді:


4

CJam, 31

q~L{_:&\f{_2$f#:).>j+}{,}$W>s}j

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

9 байт в гольф завдяки Деннісу!

Пояснення:

Цей алгоритм намагається використовувати кожен можливий символ для першої позиції підрядності, замінює кожну рядок підрядком після першого появи цього символу, а потім викликає себе рекурсивно (із запам'ятовуванням).

q~          read and evaluate the input (taken as an array)
L{…}j       execute block with recursive memoization and no starting values
  _         duplicate the array of strings
  :&\       intersect the strings as character sets and move before the array
             these are all the possible characters for the sequence
  f{…}      for each character and the array
    _2$     duplicate the array and the character
    f#      find the character position in each string
    :)      increment the positions (to skip the character)
    .>      slice each string starting at the corresponding position
    j       call the j block recursively
    +       concatenate the starting character with the result
  {,}$      sort resulting strings (one for each character) by length
  W>        keep only the last element, if any
  s         convert (from 0/1-string array) to string

5

Пітон - 665 644

Рівні відступу:

1: space
2: tab
3: tab + space
4: 2 tabs
5: 2 tabs + space

Код визначає функцію o, яка приймає список рядків як аргументів і повертає один із LCS для рядків.

def o(t):
 t=[[y for y in x if y in reduce(lambda x,y:x.intersection(y),t,set(t[0]))]for x in t];l=map(len,t);C=[0]*reduce(lambda x,y:x*-~y,l,1);y=lambda z:[x-1for x in z];m=len(t);e=enumerate
 def g(h):
    r,x=0,1
    for k,j in e(h):r+=-~j*x;x*=-~l[k]
    return r
 def f(h):
    i=len(h)
    if i==m:
     b=g(h);c=t[0][h[0]]
     for k,j in e(h):
         if t[k][j]!=c:break
     else:C[b]=1+C[g(y(h))];return
     r=0
     for k,_ in e(h):a=h[:];a[k]-=1;r=max(r,C[g(a)])
     C[b]=r;return
    for j,_ in e(t[i]):f(h+[j])
 def p(h):
    if min(h)==-1:return''
    v=C[g(h)]
    for k,_ in e(h):
        a=h[:];a[k]-=1
        if v==C[g(a)]:return p(a)
    return p(y(h))+t[0][h[0]]
 f([]);return p(y(l))

Код тесту:

tests = [
"""
a
ab
""",
"""
aaaaxbbbb
bbbbxcccc
ccccxaaaa
""",
"""
hxbecqibzpyqhosszypghkdddykjfjcajnwfmtfhqcpavqrtoipocijrmqpgzoufkjkyurczxuhkcpehbhpsuieqgjcepuhbpronmlrcgvipvibhuyqndbjbrrzpqbdegmqgjliclcgahxoouqxqpujsyfwbdthteidvigudsuoznykkzskspjufgkhaxorbrdvgodlb
qnnprxqpnafnhekcxljyysobbpyhynvolgtrntqtjpxpchqwgtkpxxvmwwcohxplsailheuzhkbtayvmxnttycdkbdvryjkfhshulptkuarqwuidrnjsydftsyhuueebnrjvkfvhqmyrclehcwethsqzcyfvyohzskvgttggndmdvdgollryqoswviqurrqhiqrqtyrl
""",
"""
riikscwpvsbxrvkpymvbbpmwclizxlhihiubycxmxwviuajdzoonjpkgiuiulbjdpkztsqznhbjhymwzkutmkkkhirryabricvhb
jnrzutfnbqhbaueicsvltalvqoorafnadevojjcsnlftoskhntashydksoheydbeuwlswdzivxnvcrxbgxmquvdnfairsppodznm
kzimnldhqklxyezcuyjaiasaeslicegmnwfavllanoolkhvqkjdvxrsjapqqwnrplcwqginwinktxnkfcuuvoyntrqwwucarfvjg
""",
"""
rblartqkfggrjpiipuzzypkycnyckkcqceeujiyy
yfpnedyjtiwrhyuktripdwyvgkblzodeufkelhub
ywcyboxwqkibwvredkrbdsyudkulpvmhixeqxynh
bnxwahbzhwjxkotnvbxrojkkldtsodtjmvdrmbgr
""",
"""
bwfscmotshoczmduwaev
coywaaizdaxjovipsmeh
dobzcpoiedenzlfdjpiu
bbhfeqscvvbwkuoxdoge
drqrzwbcpcsvneodelja
""",
"""
nqrualgoedlf
jgqorzglfnpa
fgttvnogldfx
pgostsulyfug
sgnhoyjlnfvr
wdttgkolfkbt
""",
"""
epopyfuhgowedpiqpgfj
ddxyestqynpwmytxhozm
ptubgzyqqksieoovuezv
tovotqmnhgzttfpywjgr
aomvytkgaijlgqzkljls
vzvxpaixrnprxvenbbuo
syfuwxlpcyontqlmfvib
arxleuomstkjegpduwcx
xgqrxaopouvkvwgbzewn
yggunddigctgpnuztzai
izroomywwztdymqszsuo
kiawjnxjncdtufhkrjsp
"""
]

for s in tests:
 print o(s.strip().split())

Час, який потрібен для запуску тестів на моєму комп’ютері:

$ time python 52808-shortest-longest-common-subsequence-code-golfed.py
a
x
hecbpyhogntqtpcqgkxchpsieuhbncvhuqndbjqmclchqyfhtdvgoysuhrrl
icsvllvanlktywuar
krkk
code
golf

        9.03 real         8.99 user         0.03 sys

1
Ви повинні додати байт, щоб отримати код до 666 байт. Так метал. \ м /
Олексій А.

@AlexA. Так, я також зауважив, що підрахувавши байти, оскільки він включав новий рядок в останньому рядку.
Тайло

Є декілька невеликих удосконалень, які я бачу одразу, які повинні допомогти. По-перше, де завгодно (n+1), ви можете замінити його, -~nщоб зберегти 2 байти у кожному випадку. Крім того, будь-де, де ви користуєтесь mapз a lambda, замість цього використовуйте розуміння списку. Наприклад, map(lambda x:x-1,z)можна скоротити його на три байти, змінивши його на [~-x for x in z].
Каде

r,x=r+(j+1)*x,x*(l[k]+1)можна скоротити до r+=(j+1)*x;x*=(l[k]+1). Також вам це не потрібно, u=...оскільки uвикористовується лише в одному місці. Просто замініть цей код буквою u.
mbomb007

@ Віоз- і mbomb007 Дякую
Тайло

4

Pyth, 59 58 55 35 байт

L&@Fb?+yPMbeeb@FeMbeolNmyXJbdP@bdlb

Виріжте колосальні 20 байт завдяки @isaacg!

55-байтна версія:

DCHR?k!&.AH@FH?+Cm<1dHeeHql{medH1h.MlZ.eC++<Hk]<1b>HhkH

Відріжте 3 байти, змінивши .U@bZна @F(оператор складання).

58-байтна версія:

DCHR?k!&.AH.U@bZH?+Cm<1dHeeHql{medH1h.MlZ.eC++<Hk]<1b>HhkH

Відріжте байт, змінивши формат булевого умовного.

59-байтна версія:

DCHR?k|!.AH!.U@bZH?+Cm<1dHeeHql{medH1h.MlZ.eC++<Hk]<1b>HhkH

Це було важко! Пітон продовжував сегментувати! Досить впевнений, що це якась помилка, але я не зміг отримати мінімальний тестовий випадок. Що ж, добре.

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

Це досить повільно, але має зайняти менше години (сподіваємось). Я тестую свій Core i3 з 6 ГБ оперативної пам’яті, тому ваш 16-ГБ Core i7 повинен пройти через це. :)

Я також скористався функціями автоматичного запам'ятовування Pyth, щоб зробити це трохи швидше.

EDIT : @ Денніс сказав, що це проходить!

Щоб перевірити це, додайте наступний рядок:

CQ

і надайте йому список рядків за допомогою стандартного введення (наприклад ['a', 'ab']).

Пояснення до 35-байтної версії:

ВІП.

Пояснення до 55-байтної версії:

DCH                                                        define a function C that takes a list of strings H
   R                                                       return the following expression
    ?                                                      if
      !&.AH@FH                                             there are no more common letters OR all the strings are empty
     k                                                     return the empty string
              ?          ql{medH1                          else if the last character of every string is equal
               +Cm<1dHeeH                                  return the result of adding the last character to recursion with every item without its last character
                                 h.MlZ.eC++<Hk]<1b>HhkH    otherwise, return the largest result of recursing len(H) times, each time with one element's last character cut off

@Dennis Ok; Я над цим працюю.
kirbyfan64sos

@Dennis Оновлено Ви можете спробувати знову.
kirbyfan64sos

Останній тестовий випадок закінчується миттєво зараз.
Денніс

@Dennis YESSSSS !!
kirbyfan64sos

@ kirbyfan64sos Про segfault: Pyth segfault, коли глибина рекурсії надто висока, наприклад, при нескінченній рекурсії.
isaacg

4

C, 618 564 байт

d,M,N,A[9999][2];char*(R[9999][20]),b[1000];L(char**s,n){char*j[20],c,a=0;int x[n],y=n-1,z,i,t,m=0,w=1;for(;y;)x[y--]=999;for(;y<N;y++){for(i=0;i<n&&s[i]==R[y][i];i++);if(i/n){a=A[y][0];m=A[y][1];w=0;if(m+d<M||!a)goto J;else{c=a;goto K;}}}for(c=97;w&&c<'{';c++){K:t=1,y=1,z=1;for(i=0;i<n;j[i++]++){for(j[i]=s[i];*j[i]-c;j[i]++)t&=!!*j[i];y&=j[i]-s[i]>x[i]?z=0,1:0;}t&=!y;I:if(t){if(z)for(i=0;i<n;i++)x[i]=j[i]-s[i];d++,t+=L(j,n),d--,m=t>m?a=c,t:m;}}if(w){for(y=0;y<n;y++)R[N][y]=s[y];A[N][0]=a;A[N++][1]=m;}J:if(d+m>=M)M=d+m,b[d]=a;if(!d)N=0,M=0,puts(b);return m;}

І ось це не розгадано, для "читабельності":

d,M,N,A[9999][2];
char*(R[9999][20]),b[1000];
L(char**s,n){
    char*j[20],c,a=0;
    int x[n],y=n-1,z,i,t,m=0,w=1;
    for(;y;)
        x[y--]=999;
    for(;y<N;y++){
        for(i=0;i<n&&s[i]==R[y][i];i++);
        if(i/n){
            a=A[y][0];
            m=A[y][1];
            w=0;
            if(m+d<M||!a)
                goto J;
            else{
                c=a;
                goto K;
            }
        }
    }
    for(c=97;w&&c<'{';c++){
        K:
        t=1,
        y=1,
        z=1;
        for(i=0;i<n;j[i++]++){
            for(j[i]=s[i];*j[i]-c;j[i]++)
                t&=!!*j[i];
            y&=j[i]-s[i]>x[i]?z=0,1:0;
        }
        t&=!y;
        I:
        if(t){
            if(z)
                for(i=0;i<n;i++)
                    x[i]=j[i]-s[i];
            d++,
            t+=L(j,n),
            d--,
            m=t>m?a=c,t:m;
        }
    }
    if(w){
        for(y=0;y<n;y++)R[N][y]=s[y];
        A[N][0]=a;
        A[N++][1]=m;
    }
    J:
    if(d+m>=M)
        M=d+m,b[d]=a;
    if(!d)
        N=0,M=0,puts(b);
    return m;
}

Пані, панове, я допустив жахливу помилку. Він використовується , щоб бути красивіше ... А гото-менш ... Принаймні , зараз це швидко .

Ми визначаємо рекурсивну функцію, Lяка приймає як вхід масив sмасивів символів та кількість nрядків. Функція виводить отриману рядок у stdout та випадково повертає розмір у символах цієї рядки.

Підхід

Хоча код і є суперечливим, стратегія тут не надто складна. Почнемо з досить наївного рекурсивного алгоритму, який я опишу псевдокодом:

Function L (array of strings s, number of strings n), returns length:

Create array of strings j of size n;

For each character c in "a-z",
    For each integer i less than n,
         Set the i'th string of j to the i'th string of s, starting at the first appearance of c in s[i]. (e.g. j[i][0] == c)
         If c does not occur in the i'th string of s, continue on to the next c.
    end For

    new_length := L( j, n ) + 1; // (C) t = new_length
    if new_length > best_length
        best_character := c; // (C) a = best_character
        best_length := new_length; // (C) m = best_length
    end if
end For

// (C) d = current_depth_in_recursion_tree
if best_length + current_depth_in_recursion_tree >= best_found
     prepend best_character to output_string // (C) b = output_string
     // (C) M = best_found, which represents the longest common substring found at any given point in the execution.
     best_found = best_length + current_depth;
end if

if current_depth_in_recursion_tree == 0
    reset all variables, print output_string
end if 

return best_length

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

  • Під час кожного дзвінка Lперевіряйте, чи раніше нам давали цей самий вхід. Оскільки на практиці інформація передається по вказівникам на той самий набір рядків, нам насправді не доводиться порівнювати рядки, а лише локації, що чудово. Якщо ми виявимо, що ми отримали цю інформацію раніше, не потрібно проводити обчислення (більшу частину часу, але отримання виходу робить це трохи складніше), і ми можемо піти, просто повернувши довжину. Якщо ми не знайдемо відповідності, збережіть цей набір вводу / виводу для порівняння з майбутніми дзвінками. У коді С другий forцикл намагається знайти відповідність вхідному коду. Відомі вхідні покажчики зберігаються R, а відповідні значення довжини та символів зберігаються вA. Цей план кардинально вплинув на час виконання, особливо з довшими рядками.

  • Кожен раз, коли ми знаходимо місця розташування cв s, є шанс, що ми відразу дізнаємося, що те, що ми знайшли, не є оптимальним. Якщо кожне місцеположення cвідображається після якогось відомого місця розташування іншого листа, ми автоматично знаємо, що це cне призводить до оптимальної підрядки, оскільки ви можете помістити в неї ще одну букву. Це означає, що за невеликих витрат ми можемо видалити кілька сотень викликів Lдля великих рядків. У наведеному вище коді С y- це набір прапорів, якщо ми автоматично знаємо, що цей символ призводить до неоптимальної рядку, і zє набором прапор, якщо ми знайдемо символ, який має виключно більш ранні види, ніж будь-який інший відомий символ. Поточні ранні виступи персонажів зберігаються вx. Нинішня реалізація цієї ідеї дещо безладна, але майже вдвічі зросла в багатьох випадках.

З цими двома ідеями те, що не закінчилося за годину, зайняло приблизно 0,015 секунди.

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

Хронометраж

Ось декілька кодів тестування, які я запрошую вас спробувати онлайн :

#include "stdio.h"
#include "time.h"

#define SIZE_ARRAY(x) (sizeof(x) / sizeof(*x))

int main(int argc, char** argv) {
    /* Our test case */
    char* test7[] = {
        "nqrualgoedlf",
        "jgqorzglfnpa",
        "fgttvnogldfx",
        "pgostsulyfug",
        "sgnhoyjlnfvr",
        "wdttgkolfkbt"
    };

    printf("Test 7:\n\t");
    clock_t start = clock();

    /* The call to L */
    int size = L(test7, SIZE_ARRAY(test7));


    double dt = ((double)(clock() - start)) / CLOCKS_PER_SEC;
    printf("\tSize: %d\n", size);
    printf("\tElapsed time: %lf s\n", dt);

    return 0;
}

Я провів тестові приклади OP на ноутбуці, оснащеному 1,7-ГГц Intel Core i7 чіпом, з оптимізаційними налаштуваннями -Ofast. Моделювання повідомило про необхідний максимум 712 КБ. Ось приклад запуску кожного тестового випадку з тимчасовими позначками:

Test 1:
    a
    Size: 1
    Elapsed time: 0.000020 s
Test 2:
    x
    Size: 1
    Elapsed time: 0.000017 s
Test 3:
    hecbpyhogntqppcqgkxchpsieuhbmcbhuqdjbrqmclchqyfhtdvdoysuhrrl
    Size: 60
    Elapsed time: 0.054547 s
Test 4:
    ihicvaoodsnktkrar
    Size: 17
    Elapsed time: 0.007459 s
Test 5:
    krkk
    Size: 4
    Elapsed time: 0.000051 s
Test 6:
    code
    Size: 4
    Elapsed time: 0.000045 s
Test 7:
    golf
    Size: 4
    Elapsed time: 0.000040 s
Test 8:

    Size: 0
    Elapsed time: 0.000029 s


Total time: 0.062293 s

У гольфі я досить вражаю продуктивність, і оскільки людям здавалося, що швидкість (0,013624 с для завершення всіх тестових випадків у поєднанні) мого попереднього 618-байтного рішення, залиште його тут для ознайомлення:

d,M,N,A[9999][2];char*(R[9999][20]),b[1000];L(char**s,n){char*j[20],c,a=0;int x[n],y,z,i,t,m=0,w=1;for(y=0;y<n;y++)x[y]=999;for(y=0;y<N;y++){for(i=0;i<n;i++)if(s[i]!=R[y][i])break;if(i==n){a=A[y][0];m=A[y][1];w=0;if(m+d<M||!a)goto J;else{c=a;goto K;}}}for(c=97;w&&c<'{';c++){K:t=1,y=1,z=1;for(i=0;i<n;j[i++]++){for(j[i]=s[i];*j[i]-c;j[i]++)if(!*j[i]){t=0;goto I;}if(j[i]-s[i]>x[i])z=0;if(j[i]-s[i]<x[i])y=0;}if(y){t=0;}I:if(t){if(z){for(i=0;i<n;i++){x[i]=j[i]-s[i];}}d++,t+=L(j,n),d--,m=t>m?(a=c),t:m;}}if(w){for(y=0;y<n;y++)R[N][y]=s[y];A[N][0]=a;A[N++][1]=m;}J:if(d+m>=M)M=d+m,b[d]=a;if(!d)N=0,M=0,puts(b);return m;}

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


Я думав над тим, як опублікувати найшвидший виклик коду на подібну тему, але, схоже, мені більше не доведеться. 0.01s і 712KB просто вражає.
Денніс

Це просто дивовижно!
kirbyfan64sos

Переглядаючи ваше пояснення, що за чорт best_found? Він згадується лише двічі, один раз, коли він використовується в умовному режимі, а інший, коли він скидається.
kirbyfan64sos

Переглядаючи джерело С, здається, що best_foundвстановлено best_length + current_depth. Вам, мабуть, це слід згадати у поясненні!
kirbyfan64sos

@ kirbyfan64sos best_found- це глобальне ціле число, яке описує довжину найдовшої загальної підрядки, знайденої в будь-якій точці виконання. Я вкладу це в пояснення!
BrainSteel

1

Пітон 2, 285

Код:

import re
def f(s,a,b):
  if b==[]:return s+f('',[],a)
  if a==[]:return s+max([f(b[0][i],[b[0][i+1:]],b[1:]) for i in range(len(b[0]))],key=len) if b[0]!='' else ''
  return max([f(s,a+[b[0][i.start()+1:]],b[1:]) for i in re.finditer(s[-1],b[0])],key=len) if ~b[0].find(s[-1]) else ''

Використання:

print f('',[],['axbycz','xaybzc'])

Пояснення:

Це рекурсивна функція. sце персонаж, якого ми шукаємо. aмістить список рядків, нарізаних після s. bмістить список рядків ще не оброблених. fповертає найдовший загальний рядок.

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

Друга умова перевіряє, якщо ми не почнемо проходити жодну рядок, тобто ми навіть не маємо символу ( a==[]еквівалентно s==''). якщо так, ми перевіряємо кожен символ першого рядка в b.

Останній рядок переміщує перший рядок в bдо a, знаходячи кожне входження sв цьому рядку.

Під час першого дзвінка sповинен бути порожній рядок. aмає бути порожнім списком і bповинен містити всі рядки.


2
Ви повинні використовувати аргументи за замовчуванням, щоб у функцію надходили лише рядки, наприклад f(b,s='',a=[]).
feersum
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.