最短最長共通サブシーケンスコード


11

SLCSC問題を解決するためのタスク。これは、最長共通部分列問題を解決するための最短のコードを見つけることです。

二つ以上の文字列のLCSの問題に対する有効な解S 1、... S nは任意の文字列であるTの文字というように最大長のTが全てに現れるS Iと同じ順序で、T

TS iの部分文字列である必要はないことに注意してください。

文字列axbyczとにxaybzcは、長さ3の8つの共通サブシーケンスがあり ます。

abc abz ayc ayz xbc xbz xyc xyz

これらはいずれも、LCS問題の有効な解決策です。

詳細

上記で説明したように、次の規則に従って、LCS問題を解決するプログラムまたは関数を作成します。

  • 入力は、小文字のみを含む2つ以上の文字列で構成されます。

    これらの文字列は、文字列の配列または選択した区切り文字を持つ単一の文字列として読み取ることができます。

  • コードは、問題に対する可能な解決策のいずれか1つを出力する必要があります。オプションで、ラインフィードが続くか、引用符で囲まれます。

  • 文字列が1000文字よりも短く、最大20個の文字列があると想定できます。

    これらの制限内で、コードは理論的には期待どおり動作するはずです(無制限の時間とメモリが与えられます)。

  • あなたのコードは、私のマシン(Intel Core i7-3770、16 GiB RAM)で1時間以内に次のセクションの結合テストケースを完了する必要があります。

    考えられるすべてのサブシーケンスを単純に繰り返すアプローチは、時間制限に準拠しません。

  • など、このタスクを単純化する組み込みの使用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すべてではありません。その質問は、入力として2つの文字列のみを提供し、時間制限はありません。すべての既存の回答は、この質問のルールに準拠するには大きすぎる遅すぎるナイーブアプローチを使用しています。
デニス

最後の例はおそらく計算に最も時間がかかりますが、すべての文字列に表示されないすべての文字を最初に削除することにより、空の文字列を出力するのは簡単です。同じ数の文字列と文字列の長さを使用して、使用されるすべての文字がすべての文字列に表示され、LCSが少なくとも5文字程度である別の例を追加できますか?次のようなもの:ghostbin.com/paste/x9caq
Tyilo

@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

Python- 665 644

インデントレベル:

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

このコードは、o引数として文字列のリストを受け取り、文字列のLCSの1つを返す関数を定義します。

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バイトにするには、バイトを追加する必要があります。だから金属。\ m /
アレックスA.

@AlexA。ええ、また、最後の行に改行が含まれているため、バイトを数えるときに気づきました。
ティロ

すぐに役立つ小さな改善がいくつかあります。まず、を持っている場所ならどこにでも(n+1)置き換えて-~n、それぞれ2バイト節約できます。また、で使用する場合mapは、lambda代わりにリスト内包表記の使用を検討してください。たとえば、にmap(lambda x:x-1,z)変更すると、3バイト短縮できます[~-x for x in z]
カデ

r,x=r+(j+1)*x,x*(l[k]+1)に短縮できますr+=(j+1)*x;x*=(l[k]+1)。また、1つの場所でしか使用されないu=...ため、必要ありませんu。手紙をそのコードに置き換えてくださいu
mbomb007

@ Vioz-およびmbomb007ありがとう。
ティロ

4

Pyth、59 58 55 35バイト

L&@Fb?+yPMbeeb@FeMbeolNmyXJbdP@bdlb

@isaacgのおかげで、なんと20バイトも削減できます!

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はセグメンテーション違反を続けました!何らかのバグであることは確かですが、最小限のテストケースを得ることができませんでした。しかたがない。

私はこのアルゴリズムに基づいていました。これは、1つが2つの文字列のみのために設計されていることを除いて、問題ありません。さらに機能させるには、少し調整する必要がありました。その後、最後のテストケースに時間がかかりすぎたため、一般的な文字がもうない場合は再帰を終了するために追加のチェックを追加する必要がありました。

それはかなり遅いですが、必要があります(たぶん)時間未満取ります。6 GBのRAMを搭載したCore i3でテストしているので、16 GBのCore i7でこれを実行できます。:)

また、Pythの自動メモ機能を利用して、少し速くしました。

編集:@デニスは合格したと言った!

テストするには、次の行を追加します。

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セグメンテーションについて:無限の再帰など、再帰の深さが高すぎると、Pythセグメンテーションが発生します。
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ます。上記で実装した2つの主なトリックがあり、信じられないほど速度が向上しました。

  • を呼び出すたびにL、以前にこの同じ入力が与えられたかどうかを確認します。実際には、情報は同じ文字列セットへのポインタを介して渡されるため、実際には文字列を比較する必要はなく、場所だけを比較する必要があります。これは素晴らしいことです。以前にこの情報を取得したことがわかった場合、計算を実行する必要はありません(ほとんどの場合、出力を取得することでこれが少し複雑になります)。長さを返すだけで済みます。一致するものが見つからない場合は、この入力/出力のセットを保存して、将来の呼び出しと比較します。Cコードでは、2番目のforループが入力への一致を見つけようとします。既知の入力ポインターはに保存されR、対応する長さと文字出力値はに保存されますA。この計画は、特に文字列が長い場合、実行時間に大きな影響を与えました。

  • cin の位置を見つけるたびに、見つけたsものが最適ではないことがすぐにわかる可能性があります。のすべての場所が別の文字の既知の場所のc表示される場合、これは最適な部分文字列にならないことを自動的に認識します。これは、小さなコストで、大きな文字列に対する数百の呼び出しを潜在的に削除できることを意味します。上記のCコードでは、この文字が次善の文字列につながることが自動的にわかっている場合はフラグセットであり、他の既知の文字よりも前に出現する文字のみが見つかった場合はフラグセットです。キャラクターの現在の最も早い出現はに保存されますcLyzx。このアイデアの現在の実装は少し厄介ですが、多くの場合パフォーマンスがほぼ2倍になります。

これら2つのアイデアにより、1時間で終了しなかったものは約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;
}

1.7 GHz Intel Core i7チップを搭載したラップトップでOPのテストケースを実行し、最適化設定をに設定しました-Ofast。シミュレーションでは、712KBのピークが必要であると報告されました。次に、タイミングを指定した各テストケースの実行例を示します。

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

ゴルフでは、かなりパフォーマンスが向上しました。以前の618バイトソリューションのブルートスピード(すべてのテストケースを完了するには0.013624秒)を好むように思われたので、参照用にここに残します。

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ですか?条件で使用されている場合とリセットされている場合の2回だけ言及されています。
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、より一般的な文字を探して探します。

2番目の条件は、文字列の検索を開始していないかどうかをチェックします。つまり、文字もありません(a==[]に相当s=='')。その場合、の最初の文字列の各文字をチェックしbます。

最後の行はの最初の文字列を移動bするaの各発生を見つけることによって、sこの文字列に。

最初の呼び出しでsは、空の文字列である必要があります。a空のリストで、bすべての文字列が含まれている必要があります。


2
のように、文字列のみを関数に提供する必要があるように、デフォルト引数を使用する必要がありますf(b,s='',a=[])
feersum
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.