Mã hậu quả chung ngắn nhất dài nhất


11

Nhiệm vụ của bạn là giải quyết vấn đề SLCSC, bao gồm việc tìm mã ngắn nhất có thể để giải quyết vấn đề Hậu quả chung dài nhất .

Một giải pháp có giá trị cho vấn đề LCS cho hai hay nhiều chuỗi S 1 , S ... n là bất kỳ chuỗi T có độ dài tối đa như vậy mà nhân vật của T xuất hiện trong tất cả các S i , theo thứ tự như trong T .

Lưu ý rằng T không phải là một chuỗi con của S i .

Thí dụ

Các chuỗi axbyczxaybzccó 8 chuỗi chung có độ dài 3:

abc abz ayc ayz xbc xbz xyc xyz

Bất kỳ trong số này sẽ là một giải pháp hợp lệ cho vấn đề LCS.

Chi tiết

Viết chương trình hoặc hàm giải quyết vấn đề LCS, như đã giải thích ở trên, tuân thủ các quy tắc sau:

  • Đầu vào sẽ bao gồm hai hoặc nhiều chuỗi chỉ chứa các chữ cái viết thường.

    Bạn có thể đọc các chuỗi đó dưới dạng một chuỗi các chuỗi hoặc một chuỗi với một dấu phân cách bạn chọn.

  • Mã của bạn phải xuất bất kỳ một trong những giải pháp có thể cho vấn đề, tùy ý theo sau là một nguồn cấp dữ liệu hoặc được bao quanh bởi dấu ngoặc kép.

  • Bạn có thể giả sử rằng các chuỗi ngắn hơn 1000 ký tự và có tối đa 20 chuỗi.

    Trong các giới hạn này, mã của bạn sẽ hoạt động như mong đợi trong lý thuyết (được cung cấp không giới hạn thời gian và bộ nhớ).

  • Mã của bạn phải hoàn thành các trường hợp thử nghiệm kết hợp của phần tiếp theo trong vòng một giờ trên máy của tôi (Intel Core i7-3770, RAM 16 GiB).

    Các cách tiếp cận đơn giản lặp đi lặp lại trên tất cả các chuỗi có thể sẽ không tuân thủ giới hạn thời gian.

  • Sử dụng các phần mềm dựng sẵn tầm thường hóa tác vụ này, chẳng hạn như LongestCommonSequence, không được phép.

Luật tiêu chuẩn được áp dụng.

Các trường hợp thử nghiệm

a
ab

Đầu ra: a


aaaaxbbbb
bbbbxcccc
ccccxaaaa

Đầu ra: x


hxbecqibzpyqhosszypghkdddykjfjcajnwfmtfhqcpavqrtoipocijrmqpgzoufkjkyurczxuhkcpehbhpsuieqgjcepuhbpronmlrcgvipvibhuyqndbjbrrzpqbdegmqgjliclcgahxoouqxqpujsyfwbdthteidvigudsuoznykkzskspjufgkhaxorbrdvgodlb
qnnprxqpnafnhekcxljyysobbpyhynvolgtrntqtjpxpchqwgtkpxxvmwwcohxplsailheuzhkbtayvmxnttycdkbdvryjkfhshulptkuarqwuidrnjsydftsyhuueebnrjvkfvhqmyrclehcwethsqzcyfvyohzskvgttggndmdvdgollryqoswviqurrqhiqrqtyrl

Đầu ra: hxbbpyhogntqppcqgkxchpsieuhbncvpuqndbjqmclchqyfttdvgoysuhrrlhoặc bất kỳ chuỗi con chung nào khác có cùng độ dài


riikscwpvsbxrvkpymvbbpmwclizxlhihiubycxmxwviuajdzoonjpkgiuiulbjdpkztsqznhbjhymwzkutmkkkhirryabricvhb
jnrzutfnbqhbaueicsvltalvqoorafnadevojjcsnlftoskhntashydksoheydbeuwlswdzivxnvcrxbgxmquvdnfairsppodznm
kzimnldhqklxyezcuyjaiasaeslicegmnwfavllanoolkhvqkjdvxrsjapqqwnrplcwqginwinktxnkfcuuvoyntrqwwucarfvjg

Đầu ra: icsvllvjnlktywuarhoặc bất kỳ chuỗi con chung nào khác có cùng độ dài


rblartqkfggrjpiipuzzypkycnyckkcqceeujiyy
yfpnedyjtiwrhyuktripdwyvgkblzodeufkelhub
ywcyboxwqkibwvredkrbdsyudkulpvmhixeqxynh
bnxwahbzhwjxkotnvbxrojkkldtsodtjmvdrmbgr

Đầu ra: krkkhoặc bất kỳ chuỗi con chung nào khác có cùng độ dài


bwfscmotshoczmduwaev
coywaaizdaxjovipsmeh
dobzcpoiedenzlfdjpiu
bbhfeqscvvbwkuoxdoge
drqrzwbcpcsvneodelja

Đầu ra: codehoặc bất kỳ chuỗi con chung nào khác có cùng độ dài


nqrualgoedlf
jgqorzglfnpa
fgttvnogldfx
pgostsulyfug
sgnhoyjlnfvr
wdttgkolfkbt

Đầu ra: golfhoặc bất kỳ chuỗi con chung nào khác có cùng độ dài


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

Đầu ra: chuỗi rỗng



@NotthatCharles Không phải tất cả. Câu hỏi đó chỉ đưa ra hai chuỗi làm đầu vào và không có giới hạn thời gian. Tất cả các câu trả lời hiện có sử dụng các cách tiếp cận ngây thơ có cường độ quá chậm để tuân thủ các quy tắc của câu hỏi này.
Dennis

Ví dụ cuối cùng có thể mất nhiều thời gian nhất để tính toán, tuy nhiên bằng cách trước tiên loại bỏ mọi ký tự không xuất hiện trong mỗi chuỗi, việc xuất ra chuỗi trống là không đáng kể. Bạn có thể thêm một ví dụ khác có cùng số chuỗi và độ dài của chuỗi không, trong đó mỗi ký tự được sử dụng xuất hiện trong mỗi chuỗi và trong đó LCS có ít nhất 5 ký tự hoặc hơn? Một cái gì đó như: ghostbin.com/paste/x9caq
Tyilo

@Tylio Kết hợp một số logic kết thúc đệ quy sớm nếu các chuỗi không có các ký tự phổ biến hơn là khá nhiều so với trường hợp thử nghiệm cuối cùng.
Dennis

@Dennis Vậy giải pháp không nên chạy trong thời gian hợp lý với 20 chuỗi dài tùy ý 1000?
Tyilo

Câu trả lời:


4

CJam, 31 tuổi

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

Dùng thử trực tuyến

9 byte được chơi golf nhờ Dennis!

Giải trình:

Thuật toán này thử mọi ký tự có thể cho vị trí đầu tiên của chuỗi con, thay thế từng chuỗi bằng chuỗi con sau lần xuất hiện đầu tiên của ký tự đó và sau đó gọi chính nó theo cách đệ quy (có ghi nhớ).

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

Con trăn - 665 644

Cấp độ thụt:

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

Mã xác định một hàm o, lấy danh sách các chuỗi làm đối số và trả về một trong các LCS cho chuỗi.

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

Mã kiểm tra:

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

Thời gian để chạy các bài kiểm tra trên máy tính của tôi:

$ 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
Bạn nên thêm một byte để lấy mã của bạn thành 666 byte. Kim loại cũng vậy. \ m /
Alex A.

@AlexA. Vâng tôi cũng nhận thấy rằng khi đếm các byte vì nó bao gồm một dòng mới trên dòng cuối cùng.
Tyilo

Có một vài cải tiến nhỏ mà tôi thấy ngay lập tức sẽ giúp ích. Đầu tiên, bất cứ nơi nào bạn có a (n+1), bạn có thể thay thế nó -~nđể lưu 2 byte trong mỗi trường hợp. Ngoài ra, bất cứ nơi nào bạn sử dụng mapvới một lambda, hãy xem xét sử dụng hiểu danh sách thay thế. Ví dụ, map(lambda x:x-1,z)có thể rút ngắn ba byte bằng cách thay đổi nó thành [~-x for x in z].
Kade

r,x=r+(j+1)*x,x*(l[k]+1)có thể rút ngắn thành r+=(j+1)*x;x*=(l[k]+1). Ngoài ra, bạn không cần u=...uchỉ được sử dụng ở một nơi. Chỉ cần thay thế mã cho thư u.
mbomb007

@ Vioz- và mbomb007 Cảm ơn.
Tyilo 11/07/2015

4

Pyth, 59 58 55 35 byte

L&@Fb?+yPMbeeb@FeMbeolNmyXJbdP@bdlb

Cắt giảm 20 byte nhờ @isaacg!

Phiên bản 55 byte:

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

Cắt bỏ 3 byte bằng cách thay đổi .U@bZthành @F(toán tử gấp).

Phiên bản 58 byte:

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

Cắt bỏ một byte bằng cách thay đổi định dạng của một điều kiện boolean.

Phiên bản 59 byte:

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

Điều này thật khó! Python cứ cách ly! Khá chắc chắn đó là một loại lỗi, nhưng tôi không thể có được một trường hợp thử nghiệm tối thiểu. Ồ tốt

Tôi dựa trên thuật toán này . Điều này là tốt, ngoại trừ việc một được thiết kế chỉ cho hai chuỗi. Tôi đã phải điều chỉnh nó một chút để làm cho nó hoạt động nhiều hơn. Sau đó, trường hợp thử nghiệm cuối cùng đã mất quá nhiều thời gian, vì vậy tôi phải thêm một kiểm tra bổ sung để thoát khỏi đệ quy nếu không có các ký tự phổ biến hơn.

Nó khá chậm, nhưng sẽ mất ít hơn một giờ (hy vọng). Tôi đang thử nghiệm trên Core i3 của mình với 6 GB RAM, vì vậy Core i7 16 GB của bạn sẽ vượt qua điều này. :)

Tôi cũng đã tận dụng các chức năng tự động ghi nhớ của Pyth để làm cho nó nhanh hơn một chút.

EDIT : @Dennis nói rằng nó vượt qua!

Để kiểm tra nó, thêm dòng sau:

CQ

và cung cấp cho nó một danh sách các chuỗi thông qua đầu vào tiêu chuẩn (ví dụ ['a', 'ab']).

Giải thích cho phiên bản 35 byte:

WIP.

Giải thích cho phiên bản 55 byte:

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; Tôi sẽ làm việc với nó.
kirbyfan64sos

@Dennis Cập nhật. Bạn có thể thử lại ngay bây giờ.
kirbyfan64sos

Các trường hợp thử nghiệm cuối cùng kết thúc ngay bây giờ.
Dennis

@Dennis YESSSSS !!
kirbyfan64sos

@ kirbyfan64sos Giới thiệu về segfaults: segfaults Pyth khi độ sâu đệ quy quá cao, chẳng hạn như trên đệ quy vô hạn.
isaacg

4

C, 618 564 byte

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

Và ở đây, nó được làm sáng tỏ, cho "khả năng đọc":

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

Thưa quý vị, tôi đã phạm một sai lầm khủng khiếp. Nó từng đẹp hơn ... Và ít goto hơn ... Ít nhất là bây giờ thì nhanh .

Chúng tôi định nghĩa một hàm đệ quy Llấy đầu vào là một mảng scác ký tự và số nchuỗi. Hàm này đưa ra chuỗi kết quả thành thiết bị xuất chuẩn và trả về kích thước theo các ký tự của chuỗi đó.

Tiếp cận

Mặc dù mã bị sai lệch, chiến lược ở đây không quá phức tạp. Chúng tôi bắt đầu với một thuật toán đệ quy khá ngây thơ, mà tôi sẽ mô tả bằng mã giả:

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

Bây giờ, thuật toán này tự nó khá tàn bạo (nhưng có thể phù hợp với khoảng ~ 230 byte, tôi đã tìm thấy). Đây không phải là cách một người có được kết quả nhanh chóng. Thuật toán này quy mô cực kỳ kém với độ dài chuỗi. Thuật toán này , tuy nhiên, quy mô khá tốt với số lượng chuỗi lớn hơn. Trường hợp thử nghiệm cuối cùng sẽ được giải quyết gần như ngay lập tức, vì không có chuỗi snào có bất kỳ ký tự cchung nào. Có hai thủ thuật chính tôi đã thực hiện ở trên dẫn đến tăng tốc độ đáng kinh ngạc:

  • Tại mỗi cuộc gọi đến L, hãy kiểm tra xem trước đây chúng tôi có được cung cấp đầu vào tương tự không. Vì thông tin trong thực tế được truyền qua các con trỏ tới cùng một chuỗi, chúng tôi thực sự không phải so sánh các chuỗi, chỉ các vị trí, điều này thật tuyệt. Nếu chúng tôi thấy rằng chúng tôi đã nhận được thông tin này trước đây, thì không cần phải chạy qua các tính toán (hầu hết thời gian, nhưng việc có được đầu ra làm cho điều này phức tạp hơn một chút) và chúng tôi có thể thoát khỏi chỉ bằng cách trả về độ dài. Nếu chúng tôi không tìm thấy kết quả khớp, hãy lưu bộ đầu vào / đầu ra này để so sánh với các cuộc gọi trong tương lai. Trong mã C, forvòng lặp thứ hai cố gắng tìm kết quả khớp với đầu vào. Các con trỏ đầu vào đã biết được lưu vào Rvà các giá trị đầu ra ký tự và độ dài tương ứng được lưu trữ trongA. Kế hoạch này có tác động mạnh mẽ đến thời gian chạy, đặc biệt là với các chuỗi dài hơn.

  • Mỗi lần chúng tôi tìm thấy địa điểm cs, có một cơ hội chúng tôi biết ngay lập tức rằng những gì chúng tôi tìm thấy không tối ưu. Nếu mọi vị trí cxuất hiện sau một số vị trí đã biết của một chữ cái khác, chúng tôi sẽ tự động biết rằng điều này ckhông dẫn đến một chuỗi con tối ưu, bởi vì bạn có thể ghép thêm một chữ cái trong đó. Điều này có nghĩa là với một chi phí nhỏ, chúng tôi có khả năng có thể loại bỏ hàng trăm cuộc gọi đến Lcác chuỗi lớn. Trong mã C ở trên, ylà một cờ được đặt nếu chúng ta tự động biết rằng ký tự này dẫn đến một chuỗi dưới tối ưu và zlà một cờ được đặt nếu chúng ta tìm thấy một ký tự xuất hiện sớm hơn bất kỳ ký tự nào được biết. Sự xuất hiện sớm nhất hiện tại của các ký tự được lưu trữ trongx. Việc thực hiện ý tưởng này hiện tại hơi lộn xộn, nhưng hiệu suất gần gấp đôi trong nhiều trường hợp.

Với hai ý tưởng này, những gì không hoàn thành trong một giờ giờ mất khoảng 0,015 giây.

Có thể có nhiều thủ thuật nhỏ hơn có thể tăng tốc hiệu suất, nhưng tại thời điểm này, tôi bắt đầu lo lắng về khả năng chơi gôn của mình. Tôi vẫn không hài lòng với golf, vì vậy tôi có thể sẽ quay lại vấn đề này sau!

Thời gian

Đây là một số mã thử nghiệm mà tôi mời bạn dùng thử trực tuyến :

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

Tôi đã chạy các trường hợp thử nghiệm của OP trên máy tính xách tay được trang bị chip Intel Core i7 1,7 GHz, với cài đặt tối ưu hóa -Ofast. Mô phỏng báo cáo mức cao nhất là 712KB. Đây là một ví dụ chạy của từng trường hợp thử nghiệm, với thời gian:

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

Trong chơi gôn, tôi đã đạt được hiệu suất khá đáng kể và vì mọi người dường như thích tốc độ vũ phu (0,013624 giây để hoàn thành tất cả các trường hợp thử nghiệm kết hợp) của giải pháp 618 byte trước đây của tôi, tôi sẽ để nó ở đây để tham khảo:

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

Thuật toán tự nó không thay đổi, nhưng mã mới dựa trên các phép chia và một số thao tác bitwise phức tạp hơn, kết thúc làm chậm toàn bộ sự việc.


Tôi đã suy nghĩ về việc đăng một thử thách mã nhanh nhất về một chủ đề tương tự, nhưng có vẻ như tôi không phải làm thế nữa. 0,01s và 712KB chỉ là đáng kinh ngạc.
Dennis

Điều này chỉ đơn giản là tuyệt vời!
kirbyfan64sos

Nhìn qua lời giải thích của bạn, cái quái best_foundgì vậy? Nó chỉ được đề cập hai lần, một lần khi nó được sử dụng trong điều kiện và lần khác khi được đặt lại.
kirbyfan64sos

Nhìn qua nguồn C, có vẻ như best_foundđược đặt thành best_length + current_depth. Bạn có lẽ nên đề cập rằng trong lời giải thích!
kirbyfan64sos

@ kirbyfan64sos best_foundlà một số nguyên toàn cầu mô tả độ dài của chuỗi con chung dài nhất được tìm thấy tại bất kỳ điểm đã cho nào trong thực thi. Tôi sẽ giải thích điều đó!
BrainSteel

1

Con trăn 2, 285

Mã số:

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

Sử dụng:

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

Giải trình:

Đây là một hàm đệ quy. slà nhân vật chúng tôi đang tìm kiếm. achứa danh sách các chuỗi được cắt sau s. bchứa danh sách các chuỗi chưa được ràng buộc. ftrả về chuỗi chung dài nhất.

Điều kiện đầu tiên kiểm tra nếu chúng ta hoàn thành để đi qua tất cả các chuỗi. nếu vậy, nó có nghĩa slà ký tự phổ biến, và nó trở lại svà tìm kiếm các ký tự phổ biến hơn.

Điều kiện thứ hai kiểm tra xem chúng ta có bắt đầu đi qua bất kỳ chuỗi nào không, có nghĩa là chúng ta thậm chí không có một ký tự ( a==[]tương đương với s==''). nếu vậy chúng ta kiểm tra từng ký tự của chuỗi đầu tiên trong b.

Dòng cuối cùng di chuyển các chuỗi đầu tiên trong bđể a, bằng cách tìm từng xảy ra strong chuỗi này.

Trong cuộc gọi đầu tiên, snên là chuỗi rỗng. anên là danh sách trống và bnên chứa tất cả các chuỗi.


2
Bạn nên sử dụng các đối số mặc định để chỉ các chuỗi cần được cung cấp cho hàm, như thế nào f(b,s='',a=[]).
frageum
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.