En Kısa En Uzun Ortak Subququence Kodu


11

SLCSC problemini çözmek için göreviniz, en uzun ortak Subsequence problemini çözmek için mümkün olan en kısa kodu bulmaktan oluşur .

İki veya daha fazla dizeleri LCS sorununa geçerli bir çözüm S 1 , ... S n herhangi dizedir T karakterlerin öyle ki maksimal uzunluğu T tüm görünür S i de aynı sırada, T .

O Not T olmayan bir alt olmak dize ait S i .

Misal

Dizeler axbyczve xaybzcuzunluğu 3 ortak 8 alt dizileri var:

abc abz ayc ayz xbc xbz xyc xyz

Bunlardan herhangi biri LCS problemi için geçerli bir çözüm olacaktır.

ayrıntılar

LCS sorununu, yukarıda açıklandığı gibi, aşağıdaki kurallara uyarak çözen bir program veya işlev yazın:

  • Giriş yalnızca küçük harfler içeren iki veya daha fazla dizeden oluşacaktır.

    Bu dizeleri bir dizi dizisi veya istediğiniz bir sınırlayıcıya sahip tek bir dize olarak okuyabilirsiniz.

  • Kodunuzun, soruna olası çözümlerden herhangi birini, isteğe bağlı olarak satır besleme veya tırnak işaretleri içine alması gerekir.

  • Dizelerin 1000 karakterden kısa olduğunu ve en fazla 20 dizenin olduğunu varsayabilirsiniz.

    Bu sınırlar dahilinde, kodunuz teoride beklendiği gibi çalışmalıdır (sınırsız zaman ve bellek verilir).

  • Kodunuz, bir sonraki bölümün birleşik test senaryolarını makinemde bir saatten kısa bir sürede tamamlamalıdır (Intel Core i7-3770, 16 GiB RAM).

    Tüm olası alt dizileri yineleyen yaklaşımlar, zaman sınırlamasına uymayacaktır.

  • Bu görevi önemsiz hale getiren yerleşik öğelerin LongestCommonSequencekullanımına izin verilmez.

Standart kuralları geçerlidir.

Test senaryoları

a
ab

Çıktı: a


aaaaxbbbb
bbbbxcccc
ccccxaaaa

Çıktı: x


hxbecqibzpyqhosszypghkdddykjfjcajnwfmtfhqcpavqrtoipocijrmqpgzoufkjkyurczxuhkcpehbhpsuieqgjcepuhbpronmlrcgvipvibhuyqndbjbrrzpqbdegmqgjliclcgahxoouqxqpujsyfwbdthteidvigudsuoznykkzskspjufgkhaxorbrdvgodlb
qnnprxqpnafnhekcxljyysobbpyhynvolgtrntqtjpxpchqwgtkpxxvmwwcohxplsailheuzhkbtayvmxnttycdkbdvryjkfhshulptkuarqwuidrnjsydftsyhuueebnrjvkfvhqmyrclehcwethsqzcyfvyohzskvgttggndmdvdgollryqoswviqurrqhiqrqtyrl

Çıktı: hxbbpyhogntqppcqgkxchpsieuhbncvpuqndbjqmclchqyfttdvgoysuhrrlveya aynı uzunlukta başka bir ortak takip


riikscwpvsbxrvkpymvbbpmwclizxlhihiubycxmxwviuajdzoonjpkgiuiulbjdpkztsqznhbjhymwzkutmkkkhirryabricvhb
jnrzutfnbqhbaueicsvltalvqoorafnadevojjcsnlftoskhntashydksoheydbeuwlswdzivxnvcrxbgxmquvdnfairsppodznm
kzimnldhqklxyezcuyjaiasaeslicegmnwfavllanoolkhvqkjdvxrsjapqqwnrplcwqginwinktxnkfcuuvoyntrqwwucarfvjg

Çıktı: icsvllvjnlktywuarveya aynı uzunlukta başka bir ortak takip


rblartqkfggrjpiipuzzypkycnyckkcqceeujiyy
yfpnedyjtiwrhyuktripdwyvgkblzodeufkelhub
ywcyboxwqkibwvredkrbdsyudkulpvmhixeqxynh
bnxwahbzhwjxkotnvbxrojkkldtsodtjmvdrmbgr

Çıktı: krkkveya aynı uzunlukta başka bir ortak takip


bwfscmotshoczmduwaev
coywaaizdaxjovipsmeh
dobzcpoiedenzlfdjpiu
bbhfeqscvvbwkuoxdoge
drqrzwbcpcsvneodelja

Çıktı: codeveya aynı uzunlukta başka bir ortak takip


nqrualgoedlf
jgqorzglfnpa
fgttvnogldfx
pgostsulyfug
sgnhoyjlnfvr
wdttgkolfkbt

Çıktı: golfveya aynı uzunlukta başka bir ortak takip


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

Çıktı: boş dize



@NotthatCharles Hepsi değil. Bu soru girdi olarak yalnızca iki dize verir ve zaman sınırı yoktur. Mevcut tüm cevaplar, bu sorunun kurallarına uymak için çok yavaş olan saf yaklaşımlar kullanır.
Dennis

Son örnek muhtemelen hesaplamak için en uzun süreyi alır, ancak önce her dizede görünmeyen her karakteri kaldırarak boş dizenin çıktısını almak önemsizdir. Kullanılan her karakterin her dizede göründüğü ve LCS'nin en az 5 karakter olduğu aynı sayıda dizeye ve dizginin uzunluğuna sahip başka bir örnek ekleyebilir misiniz? Gibi bir şey: ghostbin.com/paste/x9caq
Tyilo

@Tylio Dizelerde daha fazla ortak karakter yoksa, özyinelemeyi erken sona erdiren bir mantık eklemek son test senaryosunun ne olduğudur.
Dennis

@Dennis Çözüm 20 keyfi uzunluktaki 1000 karakter dizisiyle makul sürede çalışamaz mı?
Tyilo

Yanıtlar:


4

CJam, 31

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

Çevrimiçi deneyin

9 bayt Dennis sayesinde golf oynuyor!

Açıklama:

Bu algoritma, alt dizinin ilk konumu için mümkün olan her karakteri dener, her dizeyi o karakterin ilk oluşumundan sonra alt dizeyle değiştirir ve sonra kendini yinelemeli olarak (notla) çağırır.

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

Girinti seviyeleri:

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

Kod, odizelerin listesini bağımsız değişken olarak alan ve dizeler için LCS'lerden birini döndüren bir işlevi tanımlar .

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

Test kodu:

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

Testleri bilgisayarımda çalıştırmak için gereken süre:

$ 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
Kodunuzu 666 bayta almak için bir bayt eklemeniz gerekir. Çok metal. \ m /
Alex

@AlexA. Evet, ayrıca baytları sayırken son satırda yeni bir satır içerdiğini de fark ettim.
Tyilo

Hemen gördüğüm yardımcı olacak birkaç küçük iyileştirme var. İlk olarak, a'nızın olduğu her yerde , her durumda 2 bayt kaydetmek için (n+1)onu değiştirebilirsiniz -~n. Ayrıca, mapa ile kullandığınız her yerde lambda, bunun yerine liste kavrama özelliğini kullanmayı düşünün. Örneğin, map(lambda x:x-1,z)üç bayt olarak değiştirilerek kısaltılabilir [~-x for x in z].
Kade

r,x=r+(j+1)*x,x*(l[k]+1)kısaltılabilir r+=(j+1)*x;x*=(l[k]+1). Ayrıca ihtiyacınız yok u=...çünkü usadece tek bir yerde kullanılıyor. Mektubun yerine bu kodu yazın u.
mbomb007

@ Vioz- ve mbomb007 Teşekkürler.
Tyilo

4

Pyth, 59 58 55 35 bayt

L&@Fb?+yPMbeeb@FeMbeolNmyXJbdP@bdlb

@İsaacg sayesinde 20 bayt kesin!

55 baytlık sürüm:

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

Değiştirerek 3 bayt kesin .U@bZiçin @F(kat) sayılabilir.

58 baytlık sürüm:

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

Bir boole koşulunun biçimini değiştirerek bir bayt kesin.

59 bayt sürümü:

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

Bu zordu! Python segfaj yapmaya devam etti! Bir tür hata olduğundan eminim, ama minimal bir test örneği alamadım. Oh iyi.

Ben kapalı algoritma tabanlı bu bir . Biri sadece iki dize için tasarlanmış olması dışında, gayet iyi. Daha fazla çalışmasını sağlamak için biraz ince ayar yapmak zorunda kaldım. Sonra, son test vakası çok uzun sürüyordu, bu yüzden daha fazla ortak karakter yoksa özyinelemeden çıkmak için ek bir kontrol eklemek zorunda kaldım.

Oldukça yavaş, ama gereken bir saat (umarım) daha az sürer. Core i3'ümü 6 GB RAM ile test ediyorum, bu nedenle 16 GB Core i7'niz bu durumdan geçmelidir. :)

Ayrıca biraz daha hızlı hale getirmek için Pyth'in otomatik hatırlama işlevlerinden de yararlandım.

EDIT : @Dennis geçtiğini söyledi!

Test etmek için aşağıdaki satırı ekleyin:

CQ

ve standart girdi (örneğin ['a', 'ab']) aracılığıyla dizelerin bir listesini verin .

35 bayt sürümü için açıklama:

WIP.

55 baytlık sürüm için açıklama:

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; Üzerinde çalışacağım.
kirbyfan64sos

@Dennis Güncellendi. Şimdi tekrar deneyebilirsiniz.
kirbyfan64sos

Son test senaryosu şimdi anında bitiyor.
Dennis

@Dennis YESSSSS !!
kirbyfan64sos

@ kirbyfan64sos Segfaultlar hakkında: Sonsuz özyineleme gibi özyineleme derinliği çok yükseldiğinde pyth segfaultlar.
isaacg

4

C 618 564 bayt

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;}

Ve burada "okunabilirlik" için çözülmüş değil:

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;
}

Bayanlar ve baylar, korkunç bir hata yaptım. Bu kullanılan güzel olmak ... Ve git-az ... En azından artık öyle hızlı .

LGirdi olarak bir dizi skarakter dizisi ve ndize sayısı alan özyinelemeli bir işlev tanımlarız . İşlev, sonuçta elde edilen dizgiyi stdout'a verir ve bu dizenin karakterlerindeki boyutu arada bir döndürür.

Yaklaşım

Kod kıvrımlı olmasına rağmen, buradaki strateji çok karmaşık değil. Sahte kod ile açıklayacağım oldukça saf bir özyinelemeli algoritma ile başlıyoruz:

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

Şimdi, bu algoritma kendi başına oldukça iğrenç (ama yaklaşık ~ 230 bayt sığabilir, buldum). Bu şekilde hızlı sonuçlar elde edilemez. Bu algoritma, dize uzunluğu ile inanılmaz derecede kötü ölçekleniyor. Bununla birlikte, bu algoritma çok sayıda dizeyle oldukça iyi ölçeklenir. Son test senaryosu neredeyse anında çözülebilir, çünkü hiçbir dizgenin ortak skarakteri yoktur c. Yukarıda uyguladığım, inanılmaz bir hız artışı ile sonuçlanan iki ana hile vardı:

  • Her çağrıda L, daha önce aynı girişin bize verilip verilmediğini kontrol edin. Pratikte bilgiler işaretçiler aracılığıyla aynı dizelere aktarıldığından, aslında dizeleri karşılaştırmak zorunda değiliz , sadece konumlar, bu harika. Bu bilgiyi daha önce aldığımızı fark edersek, hesaplamalardan geçmeye gerek yoktur (çoğu zaman, ancak çıktı almak bunu biraz daha karmaşık hale getirir) ve sadece uzunluğu döndürmekten kurtulabiliriz. Bunu yaparsak değil bir eşleşme bulmak, gelecek çağrılara karşılaştırmak için giriş / çıkış bu seti kaydedin. C kodunda, ikinci fordöngü girişle eşleşmeyi bulmaya çalışır. Bilinen giriş işaretçileri kaydedilir Rve karşılık gelen uzunluk ve karakter çıkış değerleriA. Bu planın çalışma süresi üzerinde, özellikle daha uzun dizelerle büyük bir etkisi oldu.

  • Her zaman biz yerlerini bulmak ciçinde s, ne bulduk optimum olmadığını biz derhal kapalı bildiğim bir şans var. Her konumda olursa cgöründüğünü sonra başka mektupta bazı bilinen yer, biz otomatik olarak biliyorum bu o cEğer içinde bir daha mektup sığabilecek çünkü optimal alt dize yol açmaz. Bu, küçük bir maliyetle, Lbüyük dizeler için yüzlerce çağrıyı potansiyel olarak kaldırabileceğimiz anlamına gelir . Yukarıdaki C kodunda, yotomatik olarak bu karakterin yetersiz bir dizeye yol açtığını bilersek ayarlanmış bir işarettir vez bir bayrak kümesi bilinen herhangi bir karakterden daha erken bir görünüme sahip bir karakter bulursak bir bayrak kümesidir. Geçerli karakterlerin en eski görünümlerix. Bu fikrin mevcut uygulaması biraz dağınık, ancak birçok durumda performansı neredeyse iki katına çıkardı.

Bu iki fikirle, bir saat içinde bitmeyen şey yaklaşık 0.015 saniye sürdü.

Muhtemelen performansı hızlandıracak çok daha küçük püf noktaları var, ancak bu noktada her şeyi golf oynama yeteneğim hakkında endişelenmeye başladım. Ben hala golf memnun değilim, bu yüzden muhtemelen daha sonra geri gelecektir!

zamanlamalar

Sizi çevrimiçi denemeye davet ettiğim bazı test kodları :

#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'nin test senaryolarını 1,7 GHz Intel Core i7 çip ile donatılmış bir dizüstü bilgisayarda, optimizasyon ayarı ile çalıştırdım -Ofast. Simülasyon, 712KB'lik bir pik gerekli olduğunu bildirdi. Her test vakasının zamanlamaları olan bir örnek çalışması:

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

Golfte, performansı oldukça önemli bir şekilde vurdum ve insanlar önceki 618 baytlık çözümümün kaba hızını (tüm test senaryolarını tamamlamak için 0.013624 s) beğenmiş gibi göründüğünden, referans için burada bırakacağı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,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;}

Algoritmanın kendisi değişmez, ancak yeni kod bölümlere ve her şeyi yavaşlatan bazı daha karmaşık bitsel işlemlere dayanır.


Ben benzer bir konu hakkında en hızlı kod meydan okuma üzerine düşünüyordum, ama artık zorunda değil gibi görünüyor. 0.01s ve 712KB sadece şaşırtıcı.
Dennis

Bu sadece şaşırtıcı!
kirbyfan64sos

Açıklamanıza baktığınızda, bu da ne best_found? Sadece iki kez, bir kez koşullu kullanıldığında ve diğeri sıfırlandığında belirtilir.
kirbyfan64sos

C kaynağı üzerinde bakıldığında görünüyor best_foundolarak ayarlanır best_length + current_depth. Muhtemelen açıklamada bunu belirtmelisiniz!
kirbyfan64sos

@ kirbyfan64sos best_found, yürütme sırasında herhangi bir noktada bulunan en uzun ortak alt dizenin uzunluğunu açıklayan küresel bir tamsayıdır. Bunu açıklamaya koyacağım!
BrainSteel

1

Python 2, 285

Kod:

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 ''

Kullanımı:

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

Açıklama:

Bu özyinelemeli bir işlevdir. saradığımız karakter. asonra dilimlenmiş dizelerin listesini içerir s. bhenüz dokunulmamış dizelerin listesini içerir. fen uzun ortak dizeyi döndürür.

İlk koşul, tüm dizeleri geçip bitmeyeceğimizi kontrol eder. öyleyse, sortak karakter anlamına gelir ve geri döner sve daha yaygın karakterler arar.

İkinci koşul, herhangi bir dizeden geçmeye başlamadığımızı kontrol eder, yani bir karakterimiz bile yoktur ( a==[]eşdeğerdir s==''). öyleyse, ilk dizenin her karakterini kontrol ederiz b.

Son satır ilk dizeyi hamle biçin ayapılan her çağrının bularak, sbu dizede.

İlk çağrıda, sboş bir dize olmalıdır. aboş liste bolmalı ve tüm dizeleri içermelidir.


2
Varsayılan argümanları kullanmalısınız, böylece işleve yalnızca dizelerin sağlanması gerekir f(b,s='',a=[]).
feersum
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.