Самый короткий самый длинный общий код подпоследовательности


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
Tyilo

@Tylio Включение некоторой логики, которая рано заканчивает рекурсию, если строки не имеют более общих символов, - это почти то, о чем говорится в последнем тестовом примере.
Деннис

@Dennis Так что решение не должно быть в состоянии работать в разумные сроки с 20 произвольными длинами 1000 строк?
Tyilo

Ответы:


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. Да, я также заметил это при подсчете байтов, поскольку он включал новую строку в последней строке.
Tyilo

Я вижу сразу несколько небольших улучшений, которые должны помочь. Во-первых, везде, где у вас есть (n+1), вы можете заменить его, -~nчтобы сохранить 2 байта в каждом случае. Кроме того, везде, где вы используете mapс 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

@ Vioz- и mbomb007 Спасибо.
Tyilo

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

Это было сложно! Python держал сегфолтинг! Я уверен, что это была какая-то ошибка, но я не смог получить минимальный тестовый пример. Ну что ж.

Я основал алгоритм на этом . Что хорошо, за исключением того, что этот предназначен только для двух строк. Мне пришлось немного подправить его, чтобы он работал больше. Затем последний контрольный пример занял слишком много времени, поэтому мне пришлось добавить дополнительную проверку для выхода из рекурсии, если больше нет общих символов.

Это довольно медленно, но должно занять меньше часа (надеюсь). Я тестирую на своем Core i3 с 6 ГБ ОЗУ, так что ваш 16-ГБ Core i7 должен пройти через это. :)

Я также воспользовался функциями автоматического запоминания Pyth, чтобы сделать его немного быстрее.

РЕДАКТИРОВАТЬ : @ Денис сказал, что это проходит!

Чтобы проверить это, добавьте следующую строку:

CQ

и дать ему список строк через стандартный ввод (например ['a', 'ab']).

Пояснение к 35-байтовой версии:

WIP.

Пояснение к 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

Последний контрольный пример заканчивается мгновенно.
Деннис

@ Денис YESSSSS !!
kirbyfan64sos

@ kirbyfan64sos О segfaults: Pyth segfaults, когда глубина рекурсии становится слишком большой, например, при бесконечной рекурсии.
Исаак

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проверяйте, получали ли мы такой же ввод раньше. Поскольку на практике информация передается через указатели на один и тот же набор строк, нам на самом деле не нужно сравнивать строки, а просто места, и это здорово. Если мы обнаружим, что мы получили эту информацию раньше, нет необходимости выполнять расчеты (большую часть времени, но получение результатов делает это немного более сложным), и мы можем избежать простого возврата длины. Если мы не найдем соответствия, сохраните этот набор ввода / вывода для сравнения с будущими вызовами. В коде C второй forцикл пытается найти совпадения с входом. Известные входные указатели сохраняются R, а соответствующие значения длины и вывода символов сохраняются вA, Этот план оказал сильное влияние на время выполнения, особенно с более длинными строками.

  • Каждый раз, когда мы находим местоположения cв s, есть шанс, что мы сразу узнаем, что то, что мы нашли, не является оптимальным. Если каждое местоположение cпоявляется после некоторого известного местоположения другой буквы, мы автоматически знаем, что это cне приводит к оптимальной подстроке, потому что вы можете поместить в нее еще одну букву. Это означает, что за небольшую плату мы можем удалить несколько сотен вызовов Lдля больших строк. В приведенном выше коде C 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

Просматривая источник C, кажется, что best_foundон установлен в best_length + current_depth. Вероятно, вы должны упомянуть это в объяснении!
kirbyfan64sos

@ kirbyfan64sos best_found- это глобальное целое число, которое описывает длину самой длинной общей подстроки, найденной в любой заданной точке выполнения. Я добавлю это в объяснение!
BrainSteel

1

Python 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.