Số lượng tối đa của các chuỗi con duy nhất từ ​​một phân vùng


30

Tôi đã sửa đổi tiêu đề để nó dễ hiểu hơn.

Đây là một phiên bản chi tiết của câu hỏi:

Chúng tôi có một chuỗi s và muốn chia nó thành chuỗi con . Mỗi chuỗi con khác nhau. Số lượng tối đa của các chuỗi con duy nhất mà chúng ta có thể có từ một lần cắt là bao nhiêu. Nói cách khác, số lượng tối đa của các chuỗi con duy nhất được tạo thành là bao nhiêu s.

Dưới đây là một số ví dụ:

Example 1
s = 'aababaa'
output = 4
Explain: we can split `s` into aa|b|aba|a or aab|a|b|aa, 
         and 4 is the max number of substrings we can get from one split.

Example 2
s = 'aba'
output = 2
Explain: a|ba

Example 3
s = 'aaaaaaa'
output = 3
Explain: a|aa|aaaa

Lưu ý : schỉ chứa các ký tự chữ thường. Tôi không được nói bao lâu svà do đó không thể đoán được độ phức tạp thời gian tối ưu. :

Đây có phải là một vấn đề NP-hard? Nếu không, làm thế nào tôi có thể giải quyết nó một cách hiệu quả?

Tôi đã nghe vấn đề này từ một người bạn của tôi và không thể trả lời nó. Tôi đang cố gắng sử dụng Trie + tham lam để giải quyết vấn đề này. Phương pháp thất bại cho ví dụ đầu tiên.

Đây là giải pháp Trie mà tôi nghĩ ra:

def triesolution(s):
    trie = {}
    p = trie
    output = 0
    for char in s:
        if char not in p:
            output += 1
            p[char] = {}
            p = trie
        else:
            p = p[char]
    return output

Ví dụ 1, đoạn mã trên sẽ trả về 3 vì nó đang cố tách sthành a|ab|abaa.

Thêm: Nhờ ý tưởng của mọi người, có vẻ như vấn đề này rất gần với vấn đề NP. Ngay bây giờ, tôi đang cố gắng nghĩ về nó từ hướng này. Giả sử chúng ta có một chức năng Guess(n). Hàm này sẽ trả về Truenếu chúng ta có thể tìm thấy ncác chuỗi con duy nhất từ ​​một lần phân tách hoặc Falsecách khác. Một quan sát ở đây là nếu Guess(n) == True, sau đó Guess(i) == Truecho tất cả i <= n. Vì chúng ta có thể hợp nhất hai chuỗi con liền kề với nhau. Quan sát này có thể dẫn đến một giải pháp nhị phân. Tuy nhiên, nó vẫn đòi hỏi chúng ta có thể tính toán Guesshàm rất hiệu quả. Đáng buồn thay, tôi vẫn không thể tìm ra một cách tính đa thức Guess(n).


Cái đầu tiên cũng có thể được chia như aab|a|b|aavẫn còn 4
smac89

3
Vì tò mò, chuỗi của bạn có thể nhận được bao lâu?
templatetypedef

aababaa có thể được chia thành một | aa | aab | aaba | aabab | aababa | aba | ... như vậy. Làm thế nào bạn có được chỉ 4?
Suraj Motaparthy

Chuỗi chỉ chứa ahoặc b?
Phạm Trung

@PhamTrung Không, nhưng bạn có thể giả sử nó chỉ chứa ký tự chữ thường.
wqm1800

Câu trả lời:


15

Đây được gọi là sự cố phân vùng chuỗi nhận biết va chạm và được chứng minh là hoàn thành NP bằng cách giảm 3-SAT trong bài báo của Anne Condon, Ján Maňuch và Chris Thạchuk - Sự phức tạp của vấn đề phân vùng chuỗi nhận biết va chạm và liên quan đến thiết kế oligo để tổng hợp gen ( Hội nghị kết hợp và tính toán quốc tế , 265-275, 2008).


Tôi đã xem qua một cách khó hiểu trên tờ giấy đó và có vẻ như kết quả chứng minh rằng chỉ có vấn đề này là NP-hard trong trường hợp có giới hạn trên đối với số lượng ký tự có thể có trong mỗi chuỗi con. Điều đó có chính xác không? Nếu vậy, điều đó làm cho nó hơi khác so với vấn đề này. Lý do bằng cách tương tự, việc tìm kiếm MST có thể được thực hiện trong thời gian đa thức mặc dù vấn đề của Cấm tìm thấy một đối tượng MST bị ràng buộc mức độ trên các nút trong cây Lọ là NP-hard.
templatetypedef

1
Để chỉ ra rằng vấn đề này là NP-hard, chúng ta cần có thể giảm vấn đề NP-hard đã biết (phân vùng k) cho vấn đề này (phân vùng không bị ràng buộc), thay vì cách khác. Một bộ giải cho phân vùng k chắc chắn có thể giải quyết vấn đề này, nhưng điều đó không chứng minh độ cứng NP.
templatetypedef

Tôi không thấy rằng bài báo giải quyết được vấn đề: Theo tôi hiểu thì bài báo nói về vấn đề quyết định nếu tồn tại phân vùng thành các chuỗi con có độ dài tối đa k. Nếu k lớn hơn một nửa tổng chiều dài chuỗi thì vấn đề quyết định là đúng tầm thường (theo tôi hiểu).
Hans Olsson

Không, thực tế là vấn đề có một giải pháp tầm thường cho k lớn không có nghĩa là k sẽ phải nhỏ và việc giảm sẽ hoạt động.
templatetypedef

8

(Rất cám ơn Gilad Barkan (ב ž) vì đã khiến tôi biết về cuộc thảo luận này.)

Hãy để tôi chia sẻ suy nghĩ của tôi về vấn đề này từ quan điểm lý thuyết thuần túy (lưu ý rằng tôi cũng sử dụng "yếu tố" thay vì "từ khóa").

Tôi nghĩ rằng một định nghĩa đủ chính thức về vấn đề (hoặc vấn đề) được xem xét ở đây là như sau:

Cho một từ w, tìm các từ u_1, u_2, ..., u_k sao cho

  • u_i! = u_j với mọi i, j với 1 <= i <j <= k và
  • u_1 u_2 ... u_k = w

Biến thể tối đa hóa (chúng tôi muốn nhiều u_i): tối đa hóa k

Biến thể tối thiểu hóa (chúng tôi muốn u_i ngắn): tối thiểu hóa tối đa {| u_i | : 1 <= i <= k}

Những vấn đề này trở thành vấn đề quyết định bằng cách đưa ra B ràng buộc, tùy theo việc chúng ta đang nói về "nhiều yếu tố" -variant hay "các yếu tố ngắn" -variant, là giới hạn thấp hơn của k (chúng ta muốn ít nhất là B các yếu tố) hoặc giới hạn trên của max {| u_i | : 1 <= i <= k} (chúng tôi muốn các yếu tố có độ dài tối đa B), tương ứng. Để nói về độ cứng NP, chúng ta cần nói về các vấn đề quyết định.

Chúng ta hãy sử dụng thuật ngữ SF cho "các yếu tố ngắn" -variant và MF cho "nhiều yếu tố" -variant. Đặc biệt, và đây là một điểm rất quan trọng, các vấn đề được xác định theo cách chúng ta có được một từ trên một số bảng chữ cái không bị hạn chế theo bất kỳ cách nào. Phiên bản vấn đề là chúng tôi biết một tiên nghiệm mà chúng tôi chỉ nhận được các từ đầu vào, giả sử, bảng chữ cái {a, b, c, d} là một vấn đề khác! Độ cứng NP không tự động chuyển từ biến thể "không giới hạn" sang biến thể "bảng chữ cái cố định" (cái sau có thể đơn giản hơn).

Cả SF và MF đều là các bài toán NP-đầy đủ. Điều này đã được thể hiện trong [1, 1b] và [2], tương ứng (như Gilad đã chỉ ra). Nếu tôi hiểu định nghĩa vấn đề không chính thức (có thể quá) ở đây khi bắt đầu cuộc thảo luận này một cách chính xác, thì vấn đề của cuộc thảo luận này chính xác là vấn đề MF. Ban đầu người ta không đề cập rằng các từ bị hạn chế xuất phát từ một số bảng chữ cái cố định, sau đó người ta nói rằng chúng ta có thể giả sử rằng chỉ các chữ cái viết thường được sử dụng. Nếu điều này có nghĩa là chúng ta chỉ xem xét các từ trên bảng chữ cái cố định {a, b, c, ..., z}, thì điều này thực sự sẽ thay đổi rất nhiều về độ cứng NP.

Nhìn kỹ hơn cho thấy một số khác biệt về độ phức tạp của SF và MF:

  1. giấy [1, 1b] cho thấy SF vẫn hoàn thành NP nếu chúng ta sửa bảng chữ cái thành nhị phân (chính xác hơn: lấy một từ w qua các chữ cái a và b và B bị ràng buộc, chúng ta có thể tính nó theo các yếu tố độ dài khác nhau tại nhất B?).
  2. giấy [1, 1b] cho thấy SF vẫn hoàn thành NP nếu chúng ta sửa B = 2 bị ràng buộc (chính xác hơn: nhận được một từ w, chúng ta có thể tính nó theo các yếu tố khác nhau về độ dài nhiều nhất là 2 không?).
  3. giấy [3] cho thấy rằng nếu cả bảng chữ cái và B bị ràng buộc đều cố định, thì SF có thể được giải trong thời gian đa thức.
  4. giấy [2] cho thấy rằng MF là NP hoàn chỉnh, nhưng chỉ khi bảng chữ cái không bị hạn chế hoặc cố định một tiên nghiệm! Cụ thể, nó không trả lời câu hỏi nếu vấn đề là NP-đầy đủ nếu chúng ta chỉ xem xét các từ đầu vào trên một số bảng chữ cái cố định (như thường lệ trong các cài đặt thực tế).
  5. giấy [3] cho thấy rằng MF có thể được giải quyết trong thời gian đa thức nếu giới hạn đầu vào B lại bị giới hạn trên bởi một số hằng số, nghĩa là, đầu vào vấn đề là một từ và B bị ràng buộc từ {1, 2, ..., K} , trong đó K là một số hằng số cố định.

Một số nhận xét về các kết quả này: Wrt (1) và (2), rõ ràng bằng trực giác rằng nếu bảng chữ cái là nhị phân, thì để làm cho vấn đề SF trở nên khó khăn, B cũng bị ràng buộc. Ngược lại, sửa B = 2 có nghĩa là kích thước bảng chữ cái phải khá lớn để tạo ra các trường hợp khó. Kết quả là, (3) khá tầm thường (trên thực tế, [3] nói nhiều hơn một chút: sau đó chúng ta có thể giải quyết nó trong thời gian chạy không chỉ đa thức, mà còn | w | ^ 2 lần một yếu tố chỉ phụ thuộc vào kích thước bảng chữ cái và ràng buộc B). (5) cũng không khó: Nếu từ của chúng ta dài so với B, thì chúng ta có thể có được hệ số mong muốn bằng cách đơn giản là rạch vào các yếu tố có độ dài khác nhau. Nếu không, thì chúng ta có thể vũ phu tất cả các khả năng, chỉ theo cấp số nhân trong B, trong trường hợp này được coi là một hằng số.

Vì vậy, hình ảnh chúng ta có như sau: SF có vẻ khó khăn hơn, bởi vì chúng ta có độ cứng ngay cả đối với bảng chữ cái cố định hoặc đối với ràng buộc cố định B. Mặt khác, vấn đề MF, có thể giải quyết được nhiều thời gian nếu ràng buộc được cố định (trong về vấn đề này thì dễ hơn SF), trong khi câu hỏi tương ứng thì kích thước bảng chữ cái được mở. Vì vậy, MF hơi phức tạp hơn một chút so với SF, ngay cả khi hóa ra rằng MF cho bảng chữ cái cố định cũng hoàn thành NP. Tuy nhiên, nếu có thể chứng minh rằng MF có thể được giải quyết cho các bảng chữ cái cố định trong nhiều thời gian, thì MF được hiển thị là dễ dàng hơn nhiều so với SF ... bởi vì một trường hợp khó có thể là nhân tạo (bảng chữ cái không bị ràng buộc!) .

Tôi đã nỗ lực để cố gắng giải quyết trường hợp của MF với bảng chữ cái giới hạn, nhưng tôi đã không thể giải quyết nó và ngừng làm việc với nó kể từ đó. Tôi không tin rằng các nhà nghiên cứu khác đã rất cố gắng để giải quyết nó (vì vậy đây không phải là một trong những vấn đề rất khó mở này, nhiều người đã thử và thất bại; tôi coi đó là cách có thể làm được). Tôi đoán rằng đó cũng là NP-hard cho các bảng chữ cái cố định, nhưng có lẽ việc giảm quá phức tạp đến nỗi bạn sẽ nhận được một cái gì đó như "MF rất khó cho các bảng chữ cái có kích thước 35 hoặc lớn hơn" hoặc một cái gì đó, cũng không phải là siêu đẹp .

Về tài liệu tiếp theo, tôi biết bài báo [4], xem xét vấn đề tách một từ w thành các yếu tố riêng biệt u_1, u_2, ..., u_k, tất cả đều là palindromes, cũng hoàn thành NP.

Tôi đã có một cái nhìn nhanh chóng trên giấy [5], được chỉ ra bởi Gilad. Nó dường như xem xét một thiết lập khác nhau, mặc dù. Trong bài báo này, các tác giả quan tâm đến câu hỏi kết hợp về việc có bao nhiêu chuỗi con hoặc từ khóa riêng biệt có thể được chứa trong một từ nhất định, nhưng chúng có thể trùng nhau. Ví dụ: aaabaab chứa 20 từ khóa khác nhau miscounted, nhưng bạn có được ý tưởng). Một số trong số họ chỉ có một lần xuất hiện, như baa, một số trong số họ, như aa. Trong mọi trường hợp, câu hỏi không phải là làm thế nào chúng ta có thể chia từ để bằng cách nào đó có được nhiều yếu tố riêng biệt, vì điều này có nghĩa là mỗi biểu tượng riêng lẻ đóng góp vào chính xác một yếu tố.

Về các giải pháp thực tế cho các loại vấn đề này (hãy nhớ rằng tôi là một nhà lý luận, vì vậy hãy dùng nó với hạt muối):

  • Theo hiểu biết của tôi, không có giới hạn lý thuyết nào thấp hơn (như độ cứng NP) sẽ loại trừ nó để giải quyết MF trong thời gian đa thức nếu chúng ta chỉ xem xét các từ đầu vào trên một bảng chữ cái cố định. Tuy nhiên, có một cảnh báo: Nếu bạn nhận được thuật toán đa thời gian, thì thuật toán này sẽ chạy theo cấp số nhân theo số lượng ký hiệu từ bảng chữ cái cố định (hoặc hàm mũ theo một số hàm của hàm đó)! Nếu không, nó cũng sẽ là một thuật toán thời gian đa thức cho trường hợp bảng chữ cái không giới hạn. Vì vậy, là một nhà lý thuyết, tôi sẽ tìm kiếm các nhiệm vụ thuật toán có thể được tính theo cấp số mũ theo thời gian nếu số lượng ký hiệu và bằng cách nào đó giúp đưa ra thuật toán cho MF. Mặt khác, có khả năng thuật toán như vậy không tồn tại và MF cũng là NP-hard trong trường hợp bảng chữ cái cố định.

  • Nếu bạn quan tâm đến các giải pháp pratical, có thể hữu ích để ước chừng giải pháp. Vì vậy, hệ số nhận được đảm bảo chỉ lớn bằng một nửa so với mức tối ưu trong trường hợp xấu nhất sẽ không quá tệ.

  • Heuristic không đưa ra một tỷ lệ gần đúng có thể chứng minh được, nhưng hoạt động tốt trong một môi trường thực tế cũng sẽ rất thú vị, tôi đoán vậy.

  • Việc chuyển đổi các trường hợp vấn đề thành các trường hợp SAT hoặc ILP không quá khó và sau đó bạn có thể chạy SAT hoặc ILP-Solver để có được các giải pháp tối ưu.

  • Ý kiến ​​cá nhân của tôi là mặc dù không biết liệu trường hợp bảng chữ cái cố định của MF có phải là NP-hard hay không, nhưng có đủ những hiểu biết lý thuyết cho thấy vấn đề này đủ khó để có thể tìm ra giải pháp heuristic, v.v. làm việc tốt trong một môi trường thực tế


Thư mục:

[1] Anne Condon, Ján Manuch, Chris Thạchuk: Sự phức tạp của phân vùng chuỗi. J. Thuật toán rời rạc 32: 24-43 (2015)

[1b] Anne Condon, Ján Manuch, Chris Thạchuk: Sự phức tạp của vấn đề phân vùng chuỗi va chạm-nhận thức và mối liên quan của nó với thiết kế Oligo cho tổng hợp gen. COCOON 2008: 265-275

[2] Henning Fernau, Florin Manea, Robert Mercas, Markus L. Schmid: Kết hợp mô hình với các biến: Thuật toán nhanh và kết quả độ cứng mới. STACS 2015: 302-315

[3] Markus L. Schmid: Tính toán các yếu tố chuỗi không bình đẳng và lặp đi lặp lại. Lý thuyết. Tính toán. Khoa học. 618: 42-51 (2016)

[4] Hideo Bannai, Travis Gagie, Shunsuke Inenaga, Juha Kärkkäinen, Dominik Kempa, Marcin Piatkowski, Shiho Sugimoto: Yếu tố Palindromic đa dạng là NP-Complete. Nội bộ J. Tìm thấy. Tính toán. Khoa học. 29 (2): 143-164 (2018)

[5] Abraham Flaxman, Aram Wettroth Harrow, Gregory B. Sorkin: Chuỗi với tối đa nhiều hậu quả và chất nền khác biệt. Điện tử J. Lược. 11 (1) (2004)


(Cảm ơn bạn đã đăng bài, nhân tiện!) Chỉ cần làm rõ, nhận xét của tôi ở trên về tài liệu tham khảo [5], thực sự là về một câu hỏi khác - đó là câu trả lời cho câu hỏi của LukStorms trong phần bình luận chính , "Đối với bất kỳ chuỗi N nào độ dài của P ký tự có thể, tối đa các chuỗi con duy nhất như vậy có thể chứa những gì? "
גלעד

3

Đây là một giải pháp nhưng nó thổi lên rất nhanh và không ở đâu gần một giải pháp hiệu quả. Đầu tiên, nó chia chuỗi thành một danh sách các chuỗi con duy nhất mà không cần quan tâm đến việc đặt hàng, sau đó thử sử dụng itertools.permuting để lắp lại các chuỗi con đó trở lại chuỗi ban đầu, kiểm tra hoán vị EACH để xem nó có khớp với chuỗi gốc không.

import itertools as it

def splitter(seq):                                                             
    temp = [seq]
    for x in range(1, len(seq)):
        print(seq[:x], seq[x:])
        temp.append(seq[:x])
        temp.append(seq[x:])
    return temp

if __name__ == "__main__":
    test = input("Enter a string: ")
    temp = splitter(test)
    copy = temp[::]
    condition = True
    for x in temp:
        if len(x) > 1:
            copy.extend(splitter(x))
    copy = sorted(list(set(copy)))
    print(copy)
    count = []
    for x in range(len(test)):
        item = it.permutations(copy, x)
        try:
            while True:
                temp = next(item)
                if "".join(list(temp)) == test:
                    if len(temp) == len(set(temp)):
                        count.append((len(temp), temp))
        except StopIteration:
            print('next permutation begin iteration')
            continue
    print(f"All unique splits: {count}")
    print(f"Longest unique split : {max(count)[0]}")

Đối với thử nghiệm đầu tiên, chúng tôi nhận được điều này:

All unique splits: [(1, ('aababaa',)), (2, ('a', 'ababaa')), (2, ('aa', 'babaa')), (2, 
('aab', 'abaa')), (2, ('aaba', 'baa')), (2, ('aabab', 'aa')), (2, ('aababa', 'a')), (3, 
('a', 'ab', 'abaa')), (3, ('a', 'aba', 'baa')), (3, ('a', 'abab', 'aa')), (3, ('aa', 'b',
 'abaa')), (3, ('aa', 'ba', 'baa')), (3, ('aa', 'baba', 'a')), (3, ('aab', 'a', 'baa')),
 (3, ('aab', 'ab', 'aa')), (3, ('aab', 'aba', 'a')), (3, ('aaba', 'b', 'aa')), (3,
 ('aaba', 'ba', 'a')), (4, ('a', 'aba', 'b', 'aa')), (4, ('aa', 'b', 'a', 'baa')), (4,
 ('aa', 'b', 'aba', 'a')), (4, ('aab', 'a', 'b', 'aa'))]
Longest unique split : 4

Có lẽ điều này có thể được tối ưu hóa bằng cách nào đó, nhưng mất khá nhiều giây trên máy này.


3

Tôi đã thử vấn đề này và nghĩ về vấn đề này hoặc liệu có nên tạo một phân vùng tại một chỉ mục nhất định hay không. Vì vậy, hàm này được đệ quy và tạo 2 nhánh tại mỗi chỉ mục 1. Không phân vùng tại chỉ mục i 2. Phân vùng tại chỉ mục i.

Dựa trên phân vùng tôi điền vào một bộ và sau đó trả về kích thước của bộ

def max(a,b):
    if a>b: return a
    return b



def keep(last, current, inp, map):
    # print last
    # print current
    # print map

    if len(inp) == 2 :
        if inp[0]==inp[1]: return 1
        return 2

    if current >= len(inp):
        return len(map)
    // This is when we are at the start of the string. 
    // In this case we can only do one thing not partition and thus take the entire string as a possible string.

    if current == last :
        map11 = map.copy()
        map11.add(inp[current:])
        return keep(last, current + 1, inp, map11)

    map1 = map.copy();
    if current != (len(inp)-1):
        map1.add(inp[last:current])

    map2 = map.copy()

    return max(keep(last,current+1,inp, map2), keep(current, current+1, inp, map1))

print keep(0,0,"121", set([]))
print keep(0,0,"aaaaaaa", set([]))
print keep(0,0,"aba", set([]))
print keep(0,0,"aababaa", set([]))
print keep(0,0,"21", set([]))
print keep(0,0,"22", set([]))

https://onlinegdb.com/HJynWw-iH


Cảm ơn giải pháp của bạn! Giải pháp DFS này rất rõ ràng. Tôi có một đề nghị nhỏ có thể tăng tốc keepchức năng vì set.copy()chức năng này rất tốn thời gian. Làm thế nào về việc sử dụng quay lui khi hoàn thành ngăn xếp chức năng này, loại bỏ ứng cử viên hiện tại khỏi tập hợp?
wqm1800

@ wqm1800 bạn có thể vui lòng giải thích, tôi xin lỗi tôi không hiểu chính xác. Ngay cả khi chúng tôi sử dụng backtrack, chúng tôi vẫn phải mergetách các bộ vì chúng tôi luôn phân nhánh. Do đó, nó hợp nhất hoặc sao chép. Bạn có thể giải thích?
Ravi Chandak

1
Đây là giải pháp quay lui của tôi . Điều này có thể hoạt động vì ngăn xếp hàm thực thi theo cách DFS nên khi hàm kết thúc, điều đó có nghĩa là nó đã kết thúc việc tìm kiếm tất cả các nhóm con của nó.
wqm1800

3

Bạn có thể sử dụng hàm đệ quy với một tập hợp làm tham số thứ hai để theo dõi các chuỗi duy nhất trong đường dẫn hiện tại cho đến nay. Đối với mỗi lần đệ quy, lặp qua tất cả các chỉ số cộng 1 để phân tách chuỗi cho chuỗi ứng viên có thể và nếu chuỗi ứng viên chưa có trong tập hợp, hãy thực hiện cuộc gọi đệ quy với chuỗi còn lại và ứng viên được thêm vào tập hợp để có được số lượng chuỗi con duy nhất tối đa từ chuỗi còn lại, thêm 1 vào chuỗi đó và trả về mức tối đa của số lần lặp tối đa từ các lần lặp. Trả về 0 nếu chuỗi đã cho trống hoặc tất cả các chuỗi ứng cử viên đã có trong tập hợp:

def max_unique_substrings(s, seen=()):
    maximum = 0
    for i in range(1, len(s) + 1):
        candidate = s[:i]
        if candidate not in seen:
            maximum = max(maximum, 1 + max_unique_substrings(s[i:], {candidate, *seen}))
    return maximum

Bản trình diễn: https://repl.it/@blhsing/priceyScalySphere

Trong Python 3.8, logic trên cũng có thể được viết bằng lệnh gọi maxhàm với biểu thức trình tạo lọc các ứng cử viên đã được "nhìn thấy" bằng biểu thức gán:

def max_unique_substrings(s, seen=()):
    return max((1 + max_unique_substrings(s[i:], {candidate, *seen}) for i in range(1, len(s) + 1) if (candidate := s[:i]) not in seen), default=0)

1

Đây là một câu trả lời dựa trên lý thuyết đồ thị.

Mô hình hóa
Vấn đề này có thể được mô hình hóa thành một vấn đề tập độc lập tối đa trên biểu đồ có kích thước O(n²)như sau:
Gọi w = c_1, ..., c_nlà chuỗi đầu vào.
Hãy G = (V,E)là một đồ thị vô hướng, được xây dựng như sau :
V = { (a, b) such that a,b in [1, n], a <= b }. Chúng ta có thể thấy rằng kích thước của Vn(n-1)/2, trong đó mỗi đỉnh đại diện cho một chuỗi con của w.
Sau đó, với mỗi cặp đỉnh (a1, b1)(a2, b2), chúng ta xây dựng cạnh ((a1, b1), (a2, b2))iff
(i) [a1, b1]cắt nhau [a2, b2]hoặc
(ii) c_a1...c_b1 = c_a2...c_b2.
Nói cách khác, chúng ta xây dựng một cạnh giữa hai đỉnh nếu (i) các chuỗi con mà chúng đại diện cho sự chồng chéo trong whoặc (ii) hai chuỗi con bằng nhau.

Sau đó chúng tôi có thể hiểu tại sao một bộ độc lập tối đa của Gcung cấp câu trả lời cho vấn đề của chúng tôi.

Độ phức tạp
Trong trường hợp chung, bài toán tập độc lập tối đa (MIS) là NP-hard, với độ phức tạp thời gian O(1.1996^n)và trong không gian đa thức [Xiao, NamaGoshi (2017)] .
Lúc đầu, tôi nghĩ rằng biểu đồ kết quả sẽ là một biểu đồ hợp âm (không có chu kỳ cảm ứng có độ dài> 3), điều này sẽ rất hay kể từ đó vấn đề MIS có thể được giải quyết trong thời gian tuyến tính trên lớp biểu đồ này.
Nhưng tôi nhanh chóng nhận ra rằng đó không phải là trường hợp, khá dễ dàng để tìm thấy các ví dụ trong đó có các chu kỳ cảm ứng có độ dài 5 trở lên.
Trên thực tế, biểu đồ kết quả không thể hiện bất kỳ thuộc tính 'đẹp' nào mà chúng ta thường tìm kiếm và điều đó cho phép giảm độ phức tạp của vấn đề MIS thành một đa thức.
Đây chỉ là giới hạn trên về mức độ phức tạp của vấn đề, vì việc giảm thời gian đa thức chỉ đi theo một hướng (chúng ta có thể giảm vấn đề này sang vấn đề MIS, nhưng không phải theo cách khác, ít nhất là không tầm thường). Vì vậy, cuối cùng chúng tôi kết thúc giải quyết vấn đề này trong O(1.1996^(n(n-1)/2))trường hợp xấu nhất.
Vì vậy, than ôi, tôi không thể chứng minh rằng nó ở trong P, hoặc nó là NP-hoàn chỉnh hoặc NP-hard. Một điều chắc chắn là vấn đề nằm ở NP, nhưng tôi đoán đây không phải là một bất ngờ cho bất cứ ai.

Triển khai
Ưu điểm của việc giảm vấn đề này đối với vấn đề MIS là MIS là một vấn đề cổ điển, trong đó có thể tìm thấy một số triển khai và vấn đề MIS cũng dễ dàng được viết dưới dạng ILP.
Đây là một công thức ILP của vấn đề MIS:

Objective function 
maximize sum(X[i], i in 1..n)
Constraints:
for all i in 1..n, X[i] in {0, 1}
for all edge (i, j), X[i] + X[j] <= 1

Theo tôi, đó phải là cách hiệu quả nhất để giải quyết vấn đề này (sử dụng mô hình này làm vấn đề MIS), vì bộ giải ILP có hiệu quả đáng kinh ngạc, đặc biệt là khi xảy ra trường hợp lớn.

Đây là một triển khai tôi đã sử dụng Python3 và bộ giải GLPK . Để kiểm tra nó, bạn cần một bộ giải LP tương thích với định dạng tệp Cplex.

from itertools import combinations

def edges_from_string(w):
    # build vertices
    vertices = set((a, b) for b in range(len(w)) for a in range(b+1))
    # build edges
    edges = {(a, b): set() for (a, b) in vertices}
    for (a1, b1), (a2, b2) in combinations(edges, 2):
        # case: substrings overlap
        if a1 <= a2 <= b1:
            edges[(a1, b1)].add((a2, b2))
        if a2 <= a1 <= b2:
            edges[(a2, b2)].add((a1, b1))
        # case: equal substrings
        if w[a1:b1+1] == w[a2:b2+1]:
            if a1 < a2:
                edges[(a1, b1)].add((a2, b2))
            else:
                edges[(a2, b2)].add((a1, b1))
    return edges

def write_LP_from_edges(edges, filename):
    with open(filename, 'w') as LP_file:
        LP_file.write('Maximize Z: ')
        LP_file.write("\n".join([
            "+X%s_%s" % (a, b)
            for (a, b) in edges
        ]) + '\n')
        LP_file.write('\nsubject to \n')
        for (a1, b1) in edges:
            for (a2, b2) in edges[(a1, b1)]:
                LP_file.write(
                    "+X%s_%s + X%s_%s <= 1\n" %
                    (a1, b1, a2, b2)
                )
        LP_file.write('\nbinary\n')
        LP_file.write("\n".join([
            "X%s_%s" % (a, b)
            for (a, b) in edges.keys()
        ]))
        LP_file.write('\nend\n')
write_LP_from_edges(edges_from_string('aababaa'), 'LP_file_1')
write_LP_from_edges(edges_from_string('kzshidfiouzh'), 'LP_file_2')

Sau đó, bạn có thể giải quyết chúng bằng glpsollệnh:
glpsol --lp LP_file_1
Việc aababaađược giải quyết nhanh chóng (0,02 giây trên máy tính xách tay của tôi), nhưng như mong đợi, mọi thứ trở nên khó khăn hơn khi kích thước chuỗi tăng lên ....
Chương trình này chỉ cung cấp giá trị số (chứ không phải phân vùng tối ưu), tuy nhiên phân vùng tối ưu và các chuỗi con tương ứng có thể được tìm thấy với cách triển khai tương tự, sử dụng giao diện LP solver / python như pyomo

Thời gian & bộ nhớ
aababaa : 0,02 giây, 0,4 MB, giá trị: 4
kzshidfiouzh: 1,4 giây, 3,8 MB, giá trị: 10
aababababbababab: 60,2 giây, 31,5 MB, giá trị: 8
kzshidfiouzhsdjfyu: 207,5 giây, 55,7 MB, giá trị: 14
Lưu ý rằng bộ giải LP cũng cung cấp giới hạn dưới và trên hiện tại của giải pháp, vì vậy trong ví dụ cuối cùng, tôi có thể nhận được giải pháp thực tế dưới dạng giới hạn dưới sau một phút.


Mô hình hóa không phải là giảm hoặc bằng chứng về sự phức tạp, mặc dù nó có thể hữu ích trong việc thực hiện các giải pháp. Ban đầu tôi đã viết chính mô hình này (MIS) như một bình luận dưới câu trả lời chính và sau đó đã xóa nó. Markus Schmid, một trong số ít các nhà lý thuyết cho các tác giả viết về chủ đề này đã đóng góp một câu trả lời chi tiết trên trang web này. Lớp phức tạp của vấn đề quyết định vẫn mở trong tài liệu.
גלעד

Trong trường hợp này, MIS là một hiệp hội tầm thường vì tất nhiên chúng tôi đang tìm kiếm một nhóm lớn các thứ "kết nối (cạnh) miễn phí". Ví dụ, với một bảng chữ cái một ký tự, câu trả lời là một phân vùng số mà sẽ có một giải pháp thời gian đa thức đơn giản. Có thể có các khía cạnh của vấn đề đưa ra các tối ưu hóa có thể phá vỡ LP dựa trên O (n ^ 2) được cung cấp thêm nghiên cứu và sẽ bị bỏ qua khi tạm dừng ở chế độ xem MIS. Nhưng nó có vẻ tuyệt vời cho một giải pháp làm việc chung.
גלעד

Bạn đã đọc câu trả lời của tôi? Tôi cung cấp một giảm thời gian đa thức một chiều tầm thường từ MIS cho vấn đề này, không có cách nào khác. Đối với bảng chữ cái ký tự đơn, vấn đề rõ ràng là ở P, với độ phân giải tầm thường tham lam.
m.raynal

Có vẻ như bạn đã đưa ra các giả định về lớp phức tạp của nó dựa trên MIS.
גלעד ž

Vì vậy, hãy đọc câu trả lời :-) bạn sẽ thấy không phải vậy, tôi chỉ sử dụng độ phức tạp MIS để đưa ra giới hạn trên về độ phức tạp của vấn đề. Không phải là một giới hạn dưới.
m.raynal

0

Câu trả lời khác của tôi có liên quan chặt chẽ nhưng không tương ứng chính xác với vấn đề này, không rõ liệu việc tìm ra hệ số chuỗi không có đẳng thức lớn nhất có thể thuộc một lớp phức tạp khác với việc có tồn tại bất kỳ hệ số không có đẳng thức nào với độ dài của yếu tố bị ràng buộc hay không được giải quyết bằng giấy trích dẫn).

Trong bài báo, Mô hình khớp với các biến: Thuật toán nhanh và kết quả độ cứng mới (Henning Fernau, Florin Manea, Robert Mercaş, và Markus L. Schmid, trong Hội nghị chuyên đề thứ 32 về các khía cạnh lý thuyết của khoa học máy tính, STACS 2015, tập 30 của Leibniz Các thủ tục quốc tế về Tin học (LIPIcs) , trang 302 Trực315, 2015), các tác giả cho thấy rằng NP-đầy đủ để quyết định, cho một số lượng nhất định kvà một từ w, cho dù wcó thể được đưa vào kcác yếu tố riêng biệt.

Nếu chúng ta xem xét templatetypedef của bình luận , ngụ ý có thể là một giải pháp thời gian đa thức để không hạn chế, phân tích nhân tử bình đẳng-miễn phí lớn nhất thì chắc chắn chúng ta có thể sử dụng một thuật toán như vậy để câu trả lời nếu chúng ta có thể chia chuỗi thành kyếu tố riêng biệt (chuỗi con) bằng cách đơn giản quan sát nếu klà ít hơn mức tối đa chúng ta đã biết.

Tuy nhiên, Schmid (2016) viết rằng "vẫn là một vấn đề mở cho dù MaxEFF-s vẫn hoàn thành NP nếu bảng chữ cái được cố định." (Tính toán các yếu tố chuỗi không bình đẳng và lặp đi lặp lại, Khoa học máy tính lý thuyết Tập 618 , ngày 7 tháng 3 năm 2016, Trang 42-51)

Mặc dù vậy, Kích thước hệ số tự do bình đẳng tối đa (MaxEFF-s) vẫn được tham số hóa và được định nghĩa là:

Sơ thẩm: Một từ wvà một số m, 1 ≤ m ≤ |w|.

Câu hỏi: Có tồn tại một hệ số không có đẳng thức p wvới s(p) ≥ m? ( s(p)là kích thước của hệ số.)

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.