파티션에서 고유 한 부분 문자열의 최대 수


30

제목을 좀 더 이해하기 쉽게 수정했습니다.

자세한 질문 버전은 다음과 같습니다.

우리는 문자열을 가지고 s 그것을 하위 문자열 로 나누기를 원합니다 . 각 부분 문자열은 서로 다릅니다. 한 번의 컷으로 가질 수있는 고유 한 부분 문자열의 최대 개수는 얼마입니까? 즉, form으로 연결되는 고유 한 하위 문자열의 최대 개수는 얼마입니까 s?

여기 몇 가지 예가 있어요.

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

참고 : s소문자 만 포함합니다. 나는 시간이 얼마나 길어서 s최적의 시간 복잡성을 추측 할 수 없는지에 대해서는 모른다. :(

NP- 하드 문제입니까? 그렇지 않다면 어떻게 효율적으로 해결할 수 있습니까?

내 친구 중 한 명이이 문제를 듣고 답변을들을 수 없었습니다. 이 문제를 해결하기 위해 Trie + 욕심쟁이를 사용하려고합니다. 첫 번째 예에서는이 방법이 실패합니다.

내가 생각해 낸 Trie 솔루션은 다음과 같습니다.

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

이 분할하려고하기 때문에 예를 하나 들어, 위의 코드는 3을 반환합니다 s으로 a|ab|abaa.

추가 : 모든 사람의 아이디어 덕분 에이 문제는 NP 문제와 매우 유사합니다. 지금은이 방향에서 생각하려고합니다. 함수가 있다고 가정하자 Guess(n). 이 함수는 하나의 분할 또는 다른 방식으로 고유 한 하위 문자열을 True찾을 수 있으면 반환 됩니다 . 여기서 한 가지 관찰은 , 그렇다면 모든 것 입니다. 인접한 두 개의 하위 문자열을 병합 할 수 있기 때문입니다. 이 관찰은 이진 솔루션으로 이어질 수 있습니다. 그러나 여전히 함수를 매우 효율적으로 계산할 수 있어야합니다 . 슬프게도, 나는 여전히 다항식 계산 방법을 찾을 수 없었습니다 .nFalseGuess(n) == TrueGuess(i) == Truei <= nGuessGuess(n)


첫 번째는 또한 aab|a|b|aa여전히 4 로 분할 될 수 있습니다
smac89

3
호기심으로 인해 줄이 얼마나 오래 갈 수 있습니까?
templatetypedef

aababaa는 aa | aab | aaba | aabab | aababa | aba | ... 등으로 나눌 수 있습니다. 어떻게 4를 얻었습니까?
Suraj Motaparthy

문자열에만 a또는 b?
Pham Trung

@PhamTrung 아니요, 소문자 만 포함한다고 가정 할 수 있습니다.
wqm1800

답변:


15

이것은 충돌 인식 문자열 파티션 문제 로 알려져 있으며 Anne Condon, Ján Maňuch 및 Chris Thachuk의 논문에서 3-SAT를 줄임으로써 NP- 완전으로 나타납니다-충돌 인식 문자열 파티션 문제의 복잡성 및 유전자 합성을위한 올리고 디자인과의 관계 ( International Computing and Combinatorics Conference , 265-275, 2008).


나는 그 종이를 꼼꼼히 살펴 보았고, 결과는 각 부분 문자열에있을 수있는 문자 수에 대한 상한이있는 경우이 문제가 NP-hard라는 것을 보여줍니다. 정확합니까? 그렇다면이 문제와 약간 다릅니다. "트리의 노드에 대한 정도 제약 조건에 따라 MST를 찾는"문제가 NP-hard 인 경우에도 유사하게 추론하여 다항식 시간으로 MST를 찾을 수 있습니다.
templatetypedef

1
이 문제가 NP-hard라는 것을 보여주기 위해서는 알려진 NP-hard 문제 (k-partitioning)를이 문제 (ununtrained partitioning)로 줄일 수 있어야합니다. k- 파티셔닝을위한 솔버는이 문제를 확실히 해결할 수 있지만 NP 경도를 증명하지는 않습니다.
templatetypedef

나는 종이가 문제를 해결하는 것을 보지 못합니다. 내가 이해하는 것처럼 종이는 최대 길이 k의 하위 문자열로 파티션이 있으면 결정 문제에 관한 것입니다. k가 전체 문자열 길이의 절반보다 큰 경우 결정 문제는 사소한 사실입니다 (알겠습니다).
Hans Olsson

아니요, 문제에 큰 k에 대한 사소한 해결책이 있다고해서 k가 작아야하고 축소가 작동한다는 의미는 아닙니다.
templatetypedef

8

(이 토론을 알게 해 주신 Gilad Barkan (גלעד ברקן)에게 많은 감사를드립니다.)

순전히 이론적 인 관점에서이 문제에 대한 생각을 나누겠습니다 ( "subword"대신 "factor"도 사용합니다).

여기에서 고려한 문제에 대한 공식적인 정의는 다음과 같습니다.

단어 w가 주어지면 단어 u_1, u_2, ..., u_k를 찾으십시오.

  • 모든 i에 대해 u_i! = u_j, 1 <= i <j <= k 인 j 및
  • u_1 u_2 ... u_k = w

최대화 변형 (우리는 많은 u_i를 원함) : 최대화 k

최소화 변형 (우리는 짧은 u_i를 원합니다) : 최대 최소화 {| u_i | : 1 <= i <= k}

이러한 문제는 바운드 B를 추가로 제공함으로써 의사 결정 문제가되는데, 이는 우리가 "많은 요소"-변이체 또는 "짧은 요소"-변이체에 대해 이야기하고 있는지에 따라 k의 하한입니다 (최소한 B를 원합니다) factor) 또는 max {| u_i |의 상한 : 1 <= i <= k} (우리는 최대 길이의 B를 원합니다). NP 경도에 대해 이야기하려면 의사 결정 문제에 대해 이야기해야합니다.

"짧은 요소"-변이체에 SF라는 용어를 사용하고 "많은 요소"-변이체에 대해서는 MF를 사용합시다. 특히,이 정말 중요한 점은 문제는 우리가 이상 단어를 얻을 같은 방식으로 정의된다 일부 제한 어떤 방식으로하지 않습니다 알파벳입니다. 문제 버전은 우리가 입력 단어를 얻는 것보다 우선 순위를 알고 있다는 것입니다. 예를 들어, 알파벳 {a, b, c, d}는 다른 문제입니다! NP- 경도는 "제한되지 않은"변형에서 "고정 알파벳"변형 (후자는 더 단순 할 수 있음)으로 자동 전달 되지 않습니다 .

SF와 MF는 모두 NP- 완전 문제입니다. 이것은 Gilad가 이미 지적했듯이 각각 [1, 1b] 및 [2]에 나와 있습니다. 이 토론의 시작 부분에있는 비공식적 인 문제 정의를 올바르게 이해한다면,이 토론의 문제는 정확히 MF 문제입니다. 처음에는 단어가 고정 알파벳에서 오는 것으로 제한되어 있다고 말하지 않으며 나중에 소문자 만 사용한다고 가정 할 수 있습니다. 이것이 고정 알파벳 {a, b, c, ..., z} 이상의 단어만을 고려한다는 것을 의미한다면, 이것은 실제로 NP- 경도 측면에서 많이 변할 것입니다.

자세히 살펴보면 SF와 MF의 복잡성이 약간 다릅니다.

  1. 논문 [1, 1b]는 알파벳을 이진수로 고치면 SF가 NP-complete 상태를 유지함을 보여줍니다 대부분 B?).
  2. 논문 [1, 1b]는 우리가 바운드 B = 2를 고정하면 SF가 NP-complete 상태를 유지함을 보여줍니다 (보다 정확하게 : 단어 w를 얻는다면 최대 2 개의 길이로 구별 할 수 있습니까?).
  3. 논문 [3]은 알파벳과 바운드 B가 고정되어 있으면 다항식 시간으로 SF를 풀 수 있음을 보여줍니다.
  4. 논문 [2]는 MF가 NP-complete임을 나타내지 만, 알파벳이 사전에 제한되거나 고정 되지 않은 경우에만 가능합니다 ! 특히 고정 된 알파벳보다 입력 단어 만 고려하면 문제가 NP- 완전한 경우 질문에 대답 하지 않습니다 (실제 설정의 경우와 같이).
  5. 논문 [3]은 입력 경계 B가 다시 일부 상수에 의해 상한 인 경우 다항식 시간으로 MF를 해결할 수 있음을 보여줍니다. 즉, 문제 입력은 단어 및 경계 B가 {1, 2, ..., K} 여기서 K는 고정 상수입니다.

이 결과에 대한 일부 의견 : Wrt (1) 및 (2)는 알파벳이 이진이면 문제 SF를 어렵게 만들기 위해 바운드 B도 수정할 수 없다는 것이 직관적으로 분명합니다. 반대로, B = 2를 고정한다는 것은 어려운 경우를 만들기 위해 알파벳 크기가 다소 커져야 함을 의미합니다. 결과적으로, (3)은 다소 사소합니다 (사실 [3]는 약간 더 말합니다 : 우리는 다항식뿐만 아니라 알파벳 크기에만 의존하는 요소의 | w | ^ 2 배를 실행 시간으로 해결할 수 있습니다. 바운드 B). (5)도 어렵지 않습니다 : 만약 우리의 단어가 B에 비해 길다면, 단순히 다른 길이의 요소로 슬리 팅함으로써 원하는 인수 분해를 얻을 수 있습니다. 그렇지 않다면, 우리는 모든 가능성을 무차별 적용 할 수 있는데, 이는 B에서만 기하 급수적이며,이 경우에는 일정하다고 가정합니다.

그래서 우리가 가진 그림은 다음과 같습니다. SF는 고정 알파벳이나 고정 경계 B에서도 경도를 갖기 때문에 더 어려워 보입니다. 반면에 문제 MF는 경계가 고정되면 폴리 시간을 해결할 수 있습니다. 이 점은 SF보다 쉽습니다), 해당 질문의 알파벳 크기가 열려 있습니다. 따라서 MF는 고정 알파벳의 MF도 NP가 완전하다는 것이 밝혀 지더라도 SF보다 약간 덜 복잡합니다. 그러나 고정 시간 알파벳에 대해 MF를 폴리 타임으로 해결할 수 있음을 알 수 있다면 MF는 SF보다 훨씬 쉽다는 것을 알 수 있습니다. 어려운 경우는 다소 인공적인 것이므로 (제한되지 않은 알파벳입니다!) .

알파벳 경계가있는 MF의 경우를 해결하려고 노력했지만 그 이후로 해결할 수 없었습니다. 나는 다른 연구자들이 그것을 해결하기 위해 열심히 노력했다고 생각하지 않습니다 (따라서 이것은 매우 어려운 열린 문제 중 하나가 아니며 많은 사람들이 이미 시도하고 실패했습니다. 어떻게 든 가능하다고 생각합니다). 내 생각에 그것은 고정 알파벳의 경우 NP-hard이지만, 축소가 너무 복잡하여 "MF는 35 이상의 알파벳의 경우 어렵습니다"와 같은 것을 얻을 수 있습니다. .

추가 문헌에 관해서는, 논문 [4]를 알고 있는데, 단어 w를 모든 회 문인 구별되는 요소 u_1, u_2, ..., u_k로 나누는 문제를 고려하며, 이는 NP- 완전하다.

Gilad가 지적한 논문 [5]을 간단히 살펴 보았습니다. 그러나 다른 설정을 고려하는 것 같습니다. 이 논문에서 저자들은 주어진 단어에 얼마나 많은 별개의 서브 시퀀스 나 서브 워드가 포함될 수 있는지에 대한 조합 문제에 관심이 있지만 그것들은 겹칠 수 있습니다. 예를 들어, aaabaab에는 20 개의 다른 하위 단어 a, b, aa, ab, ba, bb, aaa, aab, aba, baa, aaab, aaba, abaa, baab, aaaba, aabaa, abaab, aabaab, aaabaa, aaabaab (아마도 I) 잘못 계산되었지만 아이디어를 얻습니다). 그들 중 일부는 baa와 같이 한 번만 발생하고 일부는 aa와 같이 여러 번 발생합니다. 어쨌든 문제는 각각의 개별 기호가 정확히 하나의 요소에 기여한다는 것을 의미하기 때문에 어떻게 많은 개별 요소를 얻기 위해 어떻게 단어를 나눌 수 있는지가 아닙니다.

이런 종류의 문제에 대한 실질적인 해결책에 관해 (나는 이론가라는 것을 명심하십시오. 그래서 소금 한 알로 이것을 가져 가십시오) :

  • 내 지식으로는 고정 알파벳보다 입력 단어 만 고려하면 다항식 시간에 MF를 풀 수있는 이론적 인 하한 (NP 경도와 같은)이 없습니다. 폴리 타임 알고리즘을 얻는다면 고정 알파벳의 기호 수 (또는 그 기능에 따라 지수)로 지수 적으로 실행해야합니다! 그렇지 않으면 무제한 알파벳의 경우 다항식 시간 알고리즘이됩니다. 그래서 이론가 인 저는 심볼의 수와 MF 알고리즘을 고안하는 데 도움이되는 경우에만 시간 지수로 계산할 수있는 알고리즘 작업을 찾고있을 것입니다. 반면에, 고정 알고리즘의 경우 그러한 알고리즘이 존재하지 않고 MF도 NP-hard 일 수 있습니다.

  • 실용적인 솔루션에 관심이 있다면 솔루션을 근사화하는 것이 도움이 될 수 있습니다. 따라서 최악의 경우 최적의 절반에 불과한 인수 분해를 얻는 것은 그리 나쁘지 않습니다.

  • 가능한 근사 비율을 제공하지 않지만 실제 환경에서 잘 작동하는 휴리스틱도 흥미로울 것입니다.

  • 문제 인스턴스를 SAT 또는 ILP 인스턴스로 변환하는 것은 그리 어렵지 않아야하며 최적의 솔루션을 얻기 위해 SAT 또는 ILP-Solver를 실행할 수 있습니다.

  • 필자의 개인적 견해로는 MF의 고정-알파벳 사례가 NP-hard인지 여부는 알 수 없지만, 문제가 충분히 어렵다는 것을 암시하는 이론적 통찰력이 충분하여 휴리스틱 솔루션 등을 찾는 것이 정당하다는 것입니다. 실제 환경에서 잘 작동합니다.


서지:

[1] Anne Condon, Ján Manuch, Chris Thachuk : 문자열 분할의 복잡성. J. 이산 알고리즘 32 : 24-43 (2015)

[1b] Anne Condon, Ján Manuch, Chris Thachuk : 충돌 인식 문자열 분할 문제의 복잡성 및 유전자 합성을위한 Oligo 디자인과의 관계. COCOON 2008 : 265-275

[2] Henning Fernau, Florin Manea, Robert Mercas, Markus L. Schmid : 변수와 ​​일치하는 패턴 : 빠른 알고리즘 및 새로운 경도 결과. STACS 2015 : 302-315

[3] Markus L. Schmid : 평등이없고 반복적 인 스트링 인수 분해 계산. 이론. 계산. 공상 과학 618 : 42-51 (2016)

[4] Hideo Bannai, Travis Gagie, Shunsuke Inenaga, Juha Kärkkäinen, Dominik Kempa, Marcin Piatkowski, Shiho Sugimoto : 다양한 회문 요인 분해는 NP- 완료입니다. Int. J. 발견 계산. 공상 과학 29 (2) : 143-164 (2018)

[5] Abraham Flaxman, Aram Wettroth Harrow, Gregory B. Sorkin : 최대한 많은 고유 한 서브 시퀀스와 서브 스트링이있는 스트링. 선거인. J. 빗. 11 (1) (2004)


(참고로, 게시 주셔서 감사합니다!) 명확히하기 위해, 참고 문헌 [5]에 대한 위의 의견은 실제로 다른 질문에 관한 것이 었 습니다. 이는 주요 의견 섹션 에서 "N의 문자열 가능한 P 자 길이, 이러한 문자열에 포함 할 수있는 고유 한 하위 문자열의 최대 값은 얼마입니까? "
גלעד ברקן

3

여기에 해결책이 있지만 정말 빠르며 효율적인 해결책 근처에 있지 않습니다. 먼저 문자열을 순서에 관계없이 고유 한 하위 문자열 목록으로 분류 한 다음 itertools.permutation을 사용하여 해당 하위 문자열을 원래 문자열로 다시 어셈블하여 각 문자열이 원래 문자열과 일치하는지 테스트합니다.

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]}")

첫 번째 테스트에서는 다음을 얻습니다.

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

어쩌면 이것은 어떻게 든 최적화 될 수 있지만이 기계에서는 꽤 몇 초가 걸립니다.


3

나는이 문제를 시도하고 주어진 인덱스에서 파티션을 만들지 여부와 관련하여 생각했다. 이 함수는 재귀 적이며, 인덱스의 각 인덱스 1. 망가 파티션에서 2 가지 생성 그래서 내가 지수 전에서 2 파티션.

파티션을 기반으로 세트를 채우고 세트 크기를 반환합니다.

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


솔루션 주셔서 감사합니다! 이 DFS 솔루션은 매우 명확합니다. 함수가 시간이 많이 걸리기 keep때문에 함수를 가속화 할 수있는 작은 제안이 하나 set.copy()있습니다. 이 함수 스택을 마칠 때 역 추적을 사용하는 것은 어떻습니까? 세트에서 현재 후보를 제거합니까?
wqm1800

@ wqm1800 당신은 pls 정교한 수 있습니까, 나는 정확하게 이해하지 못해 죄송합니다. 백 트랙을 사용하더라도 merge항상 분기되므로 세트 를 분리 해야합니다 . 따라서 병합 또는 복사 중 하나입니다. 정교하게 할 수 있습니까?
라비 Chandak

1
여기 내 역 추적 솔루션이 있습니다. 이것은 함수 스택이 DFS 방식으로 실행되기 때문에 작동 할 수 있으므로 함수가 완료되면 모든 하위 트리 검색이 완료되었음을 의미합니다.
wqm1800

3

현재 경로에서 고유 한 문자열을 추적하기 위해 두 번째 매개 변수로 설정된 재귀 함수를 사용할 수 있습니다. 각 재귀에 대해 가능한 모든 후보 문자열에 대해 문자열을 분할하는 1에 1을 더한 모든 인덱스를 반복하고, 후보 문자열이 아직 세트에없는 경우 나머지 문자열과 후보를 세트에 추가하여 재귀 호출을 수행하십시오. 나머지 문자열에서 고유 한 하위 문자열의 최대 수를 얻으려면 1을 더하고 반복에서 최대 값의 최대 값을 반환하십시오. 주어진 문자열이 비어 있거나 모든 후보 문자열이 이미 세트에 있으면 0을 반환합니다.

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

데모 : https://repl.it/@blhsing/PriceyScalySphere

Python 3.8에서 위의 논리 max는 할당 표현식으로 "보인"후보를 필터링하는 생성기 표현식으로 함수를 호출하여 작성할 수도 있습니다 .

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

다음은 그래프 이론 기반 답변입니다.

모델링
이 문제하는 크기의 그래프에서 최대 독립 집합 문제로 모델링 될 수있다 O(n²): 다음과 같은
하자가 w = c_1, ..., c_n입력 문자열. 다음과 같이 빌드 된 무 방향 그래프로
하자 . 우리는의 크기가 있음을 알 수 있다 각 정점의 문자열을 나타냅니다, . 그런 다음 모든 정점 과 에 대해 모서리 iff (i) 교차 또는 (ii)을 만듭니다. 달리 말하면, 우리는 (i) 그것들이 나타내는 부분 문자열이 겹치 거나 (ii) 두 부분 문자열이 같은 경우 두 정점 사이에 가장자리를 만듭니다. G = (V,E)
V = { (a, b) such that a,b in [1, n], a <= b }Vn(n-1)/2w
(a1, b1)(a2, b2)((a1, b1), (a2, b2))
[a1, b1][a2, b2]
c_a1...c_b1 = c_a2...c_b2
w

그런 다음 최대 독립 세트G문제에 대한 해답을 제공하는 이유를 알 수 있습니다.

복잡성
일반적인 경우, 최대 독립 집합 (MIS) 문제는 O(1.1996^n)다항식 공간 의 시간 복잡성 과 다항식 공간에서 시간이 많이 걸리는 NP-hard입니다 [Xiao, NamaGoshi (2017)] .
처음에는 결과 그래프가 화음 그래프 (길이> 3의 유도 사이클 없음)라고 생각했는데, 그 이후로 MIS 문제는이 클래스의 그래프에서 선형 시간으로 해결할 수 있습니다.
그러나 나는 그것이 사실이 아니라는 것을 빨리 알게되었습니다. 길이 5 이상의 유도 된 사이클이있는 예제를 찾는 것은 매우 쉽습니다.
실제로 결과 그래프는 우리가 일반적으로 찾고있는 Mnice 문제를 나타내지 않으며 MIS 문제의 복잡성을 다항식 문제로 줄일 수 있습니다.
다항식 시간 단축은 한 방향으로 만 진행되므로 문제의 복잡성에 대한 상한 일뿐입니다 (우리는이 문제를 MIS 문제로 줄일 수 있지만 다른 방법으로는 사소하지는 않습니다). 결국 우리 O(1.1996^(n(n-1)/2))는 최악의 경우 에이 문제를 해결하게 됩니다.
아아, 나는 그것이 P에 있거나 NP가 완전하거나 NP가 어렵다는 것을 증명할 수 없었다. 한 가지 확실한 것은 문제가 NP에 있다는 것입니다. 그러나 이것은 누구에게나 놀라운 것이 아닙니다.

구현
이 문제를 MIS 문제로 줄이는 이점은 MIS가 몇 가지 구현을 찾을 수있는 고전적인 문제이며 MIS 문제도 쉽게 ILP로 작성된다는 것입니다.
다음은 MIS 문제의 ILP 공식입니다.

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

제 생각에는 ILP 솔버가 특히 큰 인스턴스에 관해서는 매우 효율적이기 때문에이 문제를 해결하는 가장 효율적인 방법이어야합니다 (이 모델링을 MIS 문제로 사용).

이것은 Python3과 GLPK 솔버를 사용하여 구현 한 것 입니다. 이를 테스트하려면 Cplex 파일 형식과 호환되는 LP 솔버가 필요합니다.

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

그런 다음 그들을 해결할 수 glpsol명령을 (내 노트북에 0.02 초) 빨리 해결하지만, 도착 예상대로 상황이 얻을 문자열의 크기가 성장함에 따라 (정도) 강하다 .... 이 프로그램은 숫자 값을 제공합니다 (그리고 그럼에도 불구하고 최적 파티션과 해당 부분 문자열은 pyomo 와 같은 LP 솔버 / 파이썬 인터페이스를 사용하여 유사한 구현으로 찾을 수 있습니다.
glpsol --lp LP_file_1
aababaa

시간 및 메모리
aababaa : 0.02 초, 0.4MB, 값 : 4
kzshidfiouzh: 1.4 초, 3.8MB, 값 : 10
aababababbababab: 60.2 초, 31.5MB, 값 : 8
kzshidfiouzhsdjfyu: 207.5 초, 55.7MB, 값 : 14
LP 솔버는 다음을 제공합니다. 솔루션의 현재 하한 및 상한을 나타내므로 마지막 예제에서는 실제 솔루션을 1 분 후에 하한으로 얻을 수 있습니다.


모델링은 솔루션을 구현하는 데 도움이 될 수 있지만 복잡성을 줄이거 나 증명하는 것은 아닙니다. 나는 원래이 모델 (MIS)을 주요 답변 아래 주석으로 작성하고 나중에 삭제했습니다. 이 주제에 관한 논문을 저술 한 소수의 이론가 중 한 사람인 Markus Schmid는 이미이 웹 페이지에 대한 자세한 답변 을 제공했습니다. 결정 문제의 복잡성 클래스는 문헌에서 여전히 열려 있습니다.
גלעד ברקן

이 경우 MIS는 일종의 사소한 협회입니다. 물론 우리는 "연결 (가장자리가없는)"의 많은 그룹을 찾고 있습니다. 예를 들어, 한 문자 알파벳의 경우 답은 간단한 다항식 시간 솔루션이있는 숫자 분할입니다. 더 많은 연구가 주어지면 O (n ^ 2) 기반 LP를 우회 할 수있는 최적화를 제공하는 문제의 측면이있을 수 있으며 MIS 관점에서 멈춤으로써 놓칠 수 있습니다. 그러나 일반적인 작업 솔루션에는 적합합니다.
גלעד ברקן

내 대답을 읽었습니까? 나는 MIS 에서이 문제로의 간단한 일방 다항식 시간 단축을 제공합니다. 단일 문자 알파벳에 관해서는, 문제는 분명히 P로, 욕심 많은 사소한 해결책입니다.
m.raynal

MIS를 기반으로하는 복잡성 클래스에 대해 가정 한 것처럼 보입니다.
גלעד ברקן

따라서 대답을 읽으십시오 :-) 당신은 그렇지 않다는 것을 알 수 있습니다. 문제의 복잡성에 상한선을두기 위해 MIS 복잡성을 사용합니다. 하한이 아닙니다.
m.raynal

0

내 다른 대답 은 밀접하게 관련되어 있지만이 문제와 정확히 일치하지는 않았기 때문에 가장 큰 등식없는 문자열 인수 분해를 찾는 것이 바운드 요인 길이 (후자)가있는 등식없는 인수 분해가 있는지 여부와 다른 복잡한 클래스가 될 수 있는지 모호합니다. 인용 된 논문에 의해 다루어 짐).

논문에서 변수와 패턴 일치 : 빠른 알고리즘 및 새로운 경도 결과 (Henning Fernau, Florin Manea, Robert Mercaş 및 Markus L. Schmid, Proc. 국제 정보 처리기구 (LIPIcs) , 302–315, 2015 페이지) 저자는 주어진 수 k와 단어 w에 대해 별개의 요소 w로 분해 할 수 있는지 여부 를 결정하는 것이 NP- 완전 함을 보여줍니다 k.

우리가 templatetypedef의 고려하는 경우 의견을 , 암시 우리에 문자열을 나눌 수 있다면 다음 확실히 우리는 대답에 같은 알고리즘을 사용 수 제한, 최대 규모의 평등이없는 인수 분해를 다항식 시간 해결책이 될 수 k별개의 요소 (문자열)을하는 경우 단순히 관찰하는 k것입니다 우리가 이미 알고있는 최대 값보다 작습니다.

그러나 Schmid (2016)는 "알파벳이 고정 된 경우 MaxEFF-s가 NP-complete로 남아 있는지 여부는 여전히 개방적인 문제"라고 기록합니다. (균등이없고 반복적 인 문자열 인수 분해 계산, 이론적 컴퓨터 과학 볼륨 618 , 2016 년 3 월 7 일, 페이지 42-51)

최대 평등없는 인수 분해 크기 (MaxEFF-s)는 여전히 매개 변수화되며 다음과 같이 정의됩니다.

인스턴스, • 단어 w와 숫자 m, 1 ≤ m ≤ |w|.

질문 :의 등식없는 인수 분해 p ws(p) ≥ m있습니까? ( s(p)요인의 크기입니다.)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.