Numero massimo di sottostringhe univoche da una partizione


30

Ho modificato il titolo in modo che sia più comprensibile.

Ecco una versione dettagliata della domanda:

Abbiamo una stringa s e vogliamo dividerla in sottostringhe . Ogni sottostringa è diversa l'una dall'altra. Qual è il numero massimo di sottostringhe uniche che possiamo avere da un taglio. In altre parole, qual è il numero massimo di sottostringhe univoche che si concatenano per formare s.

Ecco alcuni esempi:

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

Nota : scontiene solo caratteri minuscoli. Non mi è stato detto per quanto tempo se quindi non riesco a indovinare la complessità temporale ottimale. :(

È un problema NP-difficile? In caso contrario, come posso risolverlo in modo efficiente?

Ho sentito questo problema da un mio amico e non ho potuto rispondere. Sto cercando di usare un avido Trie + per risolvere questo problema. Il metodo non riesce per il primo esempio.

Ecco la soluzione Trie che mi è venuta in mente:

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

Ad esempio 1, il codice precedente restituirà 3 poiché esso prova a dividere sin a|ab|abaa.

Aggiungi: Grazie all'idea di tutti, sembra che questo problema sia molto vicino a un problema NP. In questo momento, sto provando a pensarlo da questa direzione. Supponiamo di avere una funzione Guess(n). Questa funzione tornerà Truese potessimo trovare nsottostringhe uniche da una divisione o Falsemeno. Un'osservazione qui è che se Guess(n) == True, quindi Guess(i) == Trueper tutti i <= n. Dal momento che possiamo unire insieme due sottostringhe adiacenti. Questa osservazione può portare a una soluzione binaria. Tuttavia, richiede ancora che possiamo calcolare la Guessfunzione in modo molto efficiente. Purtroppo, non riuscivo ancora a trovare un modo polinomiale per calcolare Guess(n).


Il primo può anche essere diviso in quanto aab|a|b|aaè ancora 4
smac89

3
Per curiosità, quanto tempo possono durare le tue corde?
templatetypedef

aababaa può essere diviso in | aa | aab | aaba | aabab | aababa | aba | ... e così via. Come hai ottenuto solo 4?
Suraj Motaparthy,

La stringa contiene solo ao b?
Pham Trung,

@PhamTrung No, ma puoi presumere che contenga solo caratteri minuscoli.
wqm1800,

Risposte:


15

Questo è noto come il problema della partizione di stringa sensibile alle collisioni e viene mostrato come NP completo da una riduzione da 3-SAT in un articolo di Anne Condon, Ján Maňuch e Chris Thachuk - Complessità di un problema di partizione di stringa sensibile alle collisioni e il suo relazione con la progettazione dell'oligo per la sintesi genica ( Conferenza internazionale di informatica e combinatoria , 265-275, 2008).


Ho dato una rapida occhiata a quel foglio, e sembra che il risultato dimostri che mostra solo che questo problema è NP-difficile nel caso in cui ci sia un limite superiore al numero di caratteri che possono essere presenti in ogni sottostringa. È preciso? Se è così, questo lo rende leggermente diverso da questo problema. Ragionando per analogia, trovare un MST può essere fatto in tempo polinomiale anche se il problema di "trovare un MST soggetto a un vincolo di grado sui nodi dell'albero" è NP-difficile.
templatetypedef

1
Per dimostrare che questo problema è NP-difficile, dobbiamo essere in grado di ridurre il problema NP-difficile noto (k-partizionamento) a questo problema (partizionamento non vincolato), piuttosto che il contrario. Un risolutore per il partizionamento k può sicuramente risolvere questo problema, ma ciò non dimostra la durezza NP.
templatetypedef

Non vedo che il documento risolva il problema: a quanto ho capito, il documento riguarda il problema decisionale se esiste una partizione in sottostringhe al massimo k. Se k è maggiore della metà della lunghezza totale della stringa, quel problema di decisione è banalmente vero (come ho capito).
Hans Olsson,

No, il fatto che il problema abbia una soluzione banale per k di grandi dimensioni non significa che k dovrebbe essere piccolo e la riduzione funzionerebbe.
templatetypedef

8

(Mille grazie a Gilad Barkan (גלעד ברקן) per avermi reso consapevole di questa discussione.)

Consentitemi di condividere le mie opinioni su questo problema da un punto di vista puramente teorico (si noti che uso anche "fattore" anziché "parola chiave").

Penso che una definizione sufficientemente formale del problema (o dei problemi) considerata qui sia la seguente:

Data una parola w, trova parole u_1, u_2, ..., u_k tali

  • u_i! = u_j per ogni i, j con 1 <= i <j <= k e
  • u_1 u_2 ... u_k = w

Variante di massimizzazione (ne vogliamo molti u_i): massimizza k

Variante di minimizzazione (vogliamo breve u_i): minimizzare max {| u_i | : 1 <= i <= k}

Questi problemi diventano problemi di decisione dando inoltre un limite B, che, a seconda che si parli della variante "molti fattori" o della variante "fattori corti", è un limite inferiore su k (vogliamo almeno B fattori) o un limite superiore su max {| u_i | : 1 <= i <= k} (vogliamo fattori di lunghezza al massimo B), rispettivamente. Per parlare di durezza NP, dobbiamo parlare di problemi decisionali.

Usiamo i termini SF per la "variante di fattori corti" e MF per la "variante di molti fattori". In particolare, e questo è un punto davvero cruciale, i problemi sono definiti in modo tale da ottenere una parola su qualche alfabeto che non è in alcun modo limitato. La versione del problema è che sappiamo a priori che abbiamo solo parole di input, diciamo, alfabeto {a, b, c, d} è un problema diverso! NP-difficile non non portano automaticamente dal "senza restrizioni" alla variante "alfabeto fisso" (il secondo potrebbe essere più semplice).

Sia SF che MF sono problemi NP-completi. Questo è stato mostrato in [1, 1b] e [2], rispettivamente (come Gilad ha già sottolineato). Se capisco correttamente (forse troppo) la definizione di problema informale qui all'inizio di questa discussione, allora il problema di questa discussione è esattamente il problema MF. Inizialmente non si dice che le parole siano limitate a provenire da qualche alfabeto fisso, in seguito si dice che possiamo usare solo lettere minuscole. Se ciò significa che consideriamo solo le parole sull'alfabeto fisso {a, b, c, ..., z}, allora questo cambierebbe molto in termini di durezza NP.

Uno sguardo più ravvicinato rivela alcune differenze nella complessità di SF e MF:

  1. il documento [1, 1b] mostra che SF rimane NP-completo se fissiamo l'alfabeto a uno binario (più precisamente: ottenendo una parola w sulle lettere a e b e un bordo B, possiamo fattorizzarlo in distinti fattori di lunghezza a più B?).
  2. la carta [1, 1b] mostra che SF rimane NP-completo se fissiamo il limite B = 2 (più precisamente: ottenendo una parola w, possiamo fattorizzarla in distinti fattori di lunghezza al massimo 2?).
  3. la carta [3] mostra che se sia l'alfabeto che il B legato sono fissi, allora SF può essere risolto in tempo polinomiale.
  4. paper [2] mostra che MF è NP-completo, ma solo se l'alfabeto non è limitato o risolto a priori! In particolare, non risponde alla domanda se il problema è NP-completo se consideriamo le parole di input solo su un alfabeto fisso (come al solito nelle impostazioni pratiche).
  5. la carta [3] mostra che MF può essere risolto in tempo polinomiale se i limiti di input B sono di nuovo delimitati da una costante, ovvero, l'input del problema è una parola e un limite B da {1, 2, ..., K} , dove K è una costante fissa.

Alcuni commenti su questi risultati: Wrt (1) e (2), è intuitivamente chiaro che se l'alfabeto è binario, quindi, per rendere difficile il problema SF, anche il limite B non può essere risolto. Al contrario, la correzione di B = 2 significa che la dimensione dell'alfabeto deve diventare piuttosto grande per produrre casi difficili. Di conseguenza, (3) è piuttosto banale (in effetti, [3] dice leggermente di più: possiamo quindi risolverlo in tempo di esecuzione non solo polinomiale, ma anche | w | ^ 2 volte un fattore che dipende solo dalla dimensione dell'alfabeto e legato B). (5) non è difficile: se la nostra parola è lunga rispetto a B, allora possiamo ottenere la fattorizzazione desiderata semplicemente tagliando in fattori di diversa lunghezza. Altrimenti, possiamo forzare tutte le possibilità, che è esponenziale solo in B, che in questo caso si presume sia una costante.

Quindi l'immagine che abbiamo è la seguente: SF sembra più difficile, perché abbiamo durezza anche per alfabeti fissi o per un limite fisso B. Il problema MF, d'altra parte, diventa risolvibile in poli-tempo se il limite è fisso (in a questo proposito è più semplice di SF), mentre la domanda corrispondente indica la dimensione dell'alfabeto è aperta. Quindi MF è leggermente meno complesso di SF, anche se risulta che anche MF per alfabeti fissi è NP-completo. Tuttavia, se si può dimostrare che MF può essere risolto per alfabeti fissi in tempi polifunzionali, allora MF si mostra molto più facile di SF ... perché l'unico caso per il quale è difficile è un po 'artificiale (alfabeto illimitato!) .

Ho fatto uno sforzo per cercare di risolvere il caso di MF con alfabeto limitato, ma non sono stato in grado di risolverlo e da allora ho smesso di lavorarci. Non credo che altri ricercatori abbiano cercato molto duramente di risolverlo (quindi questo non è uno di questi problemi aperti molto difficili, molte persone hanno già provato e fallito; lo considero in qualche modo fattibile). La mia ipotesi sarebbe che sia anche NP-difficile per alfabeti fissi, ma forse la riduzione è così complicata che otterresti qualcosa del tipo "MF è difficile per alfabeti di dimensioni 35 o più grandi" o qualcosa del genere, che non sarebbe neanche super bello .

Per quanto riguarda la letteratura ulteriore, conosco il documento [4], che considera il problema di dividere una parola w in fattori distinti u_1, u_2, ..., u_k che sono tutti palindromi, che è anche NP-completo.

Ho dato una rapida occhiata al documento [5], sottolineato da Gilad. Sembra considerare un ambiente diverso, però. In questo articolo, gli autori sono interessati alla domanda combinatoria di quante sottosequenze o parole chiave distinte possono essere contenute in una determinata parola, ma queste possono sovrapporsi. Ad esempio, aaabaab contiene 20 diverse parole chiave a, b, aa, ab, ba, bb, aaa, aab, aba, baa, aaab, aaba, abaa, baab, aaaba, aabaa, abaab, aabaab, aaabaa, aaabaab (forse I contato male, ma hai avuto l'idea). Alcuni di essi hanno un solo evento, come baa, altri diversi, come aa. In ogni caso, la domanda non è come possiamo in qualche modo dividere la parola per ottenere molti fattori distinti, dal momento che ciò significa che ogni singolo simbolo contribuisce esattamente a un fattore.

Per quanto riguarda le soluzioni pratiche a questo tipo di problemi (tieni presente che sono un teorico, quindi prendi questo con granello di sale):

  • Per quanto ne sappia, non ci sono limiti teorici inferiori (come la durezza NP) che escluderebbero la risoluzione di MF in tempo polinomiale se consideriamo solo le parole di input su un alfabeto fisso. C'è un avvertimento, però: se si ottiene un algoritmo poly-time, questo dovrebbe funzionare in modo esponenziale nel numero di simboli dell'alfabeto fisso (o esponenziale in alcune funzioni di questo)! Altrimenti sarebbe anche un algoritmo temporale polinomiale per il caso di alfabeti illimitati. Quindi, essendo un teorico, sarei alla ricerca di compiti algoritmici che possono essere calcolati in tempo esponenziale solo se il numero di simboli e che in qualche modo aiutano a escogitare un algoritmo per MF. D'altra parte, è probabile che un tale algoritmo non esista e che MF sia anche NP-difficile nel caso dell'alfabeto fisso.

  • Se sei interessato a soluzioni pratiche, potrebbe essere utile approssimare la soluzione. Quindi ottenere fattorizzazione che è garantita solo la metà dell'ottimale nel peggiore dei casi non sarebbe male.

  • Anche l'euristica che non fornisce un rapporto di approssimazione dimostrabile, ma che funziona bene in un contesto pratico sarebbe interessante, immagino.

  • Trasformare le istanze problematiche in istanze SAT o ILP non dovrebbe essere troppo difficile e quindi è possibile eseguire un solutore SAT o ILP per ottenere soluzioni ottimali.

  • La mia opinione personale è che anche se non è noto se il caso dell'alfabeto fisso di MF sia NP-difficile, ci sono abbastanza intuizioni teoriche che suggeriscono che il problema è abbastanza difficile da giustificare la ricerca di soluzioni euristiche ecc. funziona bene in un ambiente pratico.


Bibliografia:

[1] Anne Condon, Ján Manuch, Chris Thachuk: La complessità del partizionamento delle stringhe. J. Discrete Algorithms 32: 24-43 (2015)

[1b] Anne Condon, Ján Manuch, Chris Thachuk: Complessità di un problema di partizione di stringa consapevole della collisione e sua relazione con Oligo Design per la sintesi genica. COCOON 2008: 265-275

[2] Henning Fernau, Florin Manea, Robert Mercas, Markus L. Schmid: pattern matching con variabili: algoritmi veloci e nuovi risultati di durezza. STACS 2015: 302-315

[3] Markus L. Schmid: calcolo delle fattorizzazioni di stringhe ripetitive e prive di uguaglianza. Theor. Comput. Sci. 618: 42-51 (2016)

[4] Hideo Bannai, Travis Gagie, Shunsuke Inenaga, Juha Kärkkäinen, Dominik Kempa, Marcin Piatkowski, Shiho Sugimoto: la diversa fattorizzazione palindromica è NP-completa. Int. J. Found. Comput. Sci. 29 (2): 143-164 (2018)

[5] Abraham Flaxman, Aram Wettroth Harrow, Gregory B. Sorkin: stringhe con sequenze e sottostringi distinti al massimo. Elettr. J. Comb. 11 (1) (2004)


(Grazie per la pubblicazione, a proposito!) Giusto per chiarire, il mio commento sopra sul riferimento [5], riguardava davvero una domanda diversa - era una risposta alla domanda di LukStorms nella sezione principale dei commenti , "Per qualsiasi stringa di N lunghezza di P possibili caratteri, qual è il massimo di sottostringhe univoche che tali stringhe potrebbero contenere? "
גלעד ברקן

3

Ecco una soluzione, ma esplode molto velocemente e non è affatto vicino a una soluzione efficiente. Per prima cosa suddivide la stringa in un elenco di sottostringhe univoche senza preoccupazioni per l'ordinamento, quindi tenta di utilizzare itertools.permutation per riassemblare quelle sottostringhe nella stringa originale, testando OGNI permutazione per vedere se corrisponde alla stringa originale.

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

Per il primo test otteniamo questo:

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

Forse questo può essere ottimizzato in qualche modo, ma ci vogliono alcuni secondi su questa macchina.


3

Ho provato questo problema e ci ho pensato in termini o se creare una partizione in un determinato indice. Quindi questa funzione è ricorsiva e crea 2 rami in ciascun indice 1. Non partizionare all'indice i 2. Partizione all'indice i.

In base alla partizione compilo un set e quindi restituisco la dimensione del set

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


Grazie per la tua soluzione! Questa soluzione DFS è molto chiara. Ho un piccolo suggerimento che potrebbe accelerare la keepfunzione poiché la set.copy()funzione richiede molto tempo. Che ne dici di usare il backtracking che è quando finisci questo stack di funzioni, rimuovi il candidato corrente dal set?
wqm1800,

@ wqm1800 puoi elaborare, mi dispiace non capisco esattamente. Anche se utilizziamo il backtrack, dobbiamo comunque mergeseparare i set in quanto siamo sempre ramificati. Da qui la sua fusione o copia. Puoi elaborare?
Ravi Chandak,

1
Ecco la mia soluzione di backtracking . Questo potrebbe funzionare perché lo stack di funzioni viene eseguito come un modo DFS, quindi quando la funzione termina, significa che ha terminato la ricerca in tutto il sottstree di esso.
wqm1800,

3

È possibile utilizzare una funzione ricorsiva con un set come secondo parametro per tenere traccia delle stringhe univoche nel percorso corrente finora. Per ogni ricorsione, scorrere tutti gli indici più 1 in corrispondenza del quale dividere la stringa per una possibile stringa candidata e, se la stringa candidata non è ancora nell'insieme, effettuare una chiamata ricorsiva con la stringa rimanente e il candidato aggiunto all'insieme per ottenere il numero massimo di sottostringhe univoche dalla stringa rimanente, aggiungere 1 ad essa e restituire il massimo dei massimi dalle iterazioni. Restituisce 0 se la stringa specificata è vuota o tutte le stringhe candidate sono già nel set:

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

Demo: https://repl.it/@blhsing/PriceyScalySphere

In Python 3.8, la logica di cui sopra può anche essere scritta con una chiamata alla maxfunzione con un'espressione di generatore che filtra i candidati che sono stati "visti" con un'espressione di assegnazione:

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

Ecco una risposta basata sulla teoria dei grafi.

Modellazione
Questo problema può essere modellato come un problema di set indipendente massimo su un grafico di dimensioni O(n²)come segue:
Sia w = c_1, ..., c_nla stringa di input.
Lasciate G = (V,E)essere un grafo non orientato, costruito come segue:
V = { (a, b) such that a,b in [1, n], a <= b }. Possiamo vedere che la dimensione di Vè n(n-1)/2, dove ogni vertice rappresenta una sottostringa di w.
Quindi, per ogni coppia di vertici (a1, b1)e (a2, b2), costruiamo il bordo ((a1, b1), (a2, b2))iff
(i) [a1, b1]interseca [a2, b2]o
(ii) c_a1...c_b1 = c_a2...c_b2.
Detto altrimenti, costruiamo un bordo tra due vertici se (i) le sottostringhe che rappresentano si sovrappongono wo (ii) le due sottostringhe sono uguali.

Possiamo quindi capire perché un set indipendente massimo di Gfornisce la risposta al nostro problema.

Complessità
Nel caso generale, il problema del massimo set indipendente (MIS) è NP-difficile, con una complessità temporale O(1.1996^n)nello spazio polinomiale [Xiao, NamaGoshi (2017)] .
All'inizio ho pensato che il grafico risultante sarebbe un grafico cordale (nessun ciclo indotto di lunghezza> 3), che sarebbe stato molto bello da allora il problema MIS può essere risolto in tempo lineare su questa classe di grafici.
Ma ho presto capito che non è così, è abbastanza facile trovare esempi in cui ci sono cicli indotti di lunghezza 5 e più.
In realtà, il grafico risultante non mostra alcuna proprietà "piacevole" che di solito cerchiamo e che consente di ridurre la complessità del problema MIS a un polinomio.
Questo è solo un limite superiore alla complessità del problema, poiché la riduzione del tempo polinomiale va solo in una direzione (possiamo ridurre questo problema al problema MIS, ma non viceversa, almeno non banalmente). Quindi alla fine finiamo per risolvere questo problema nel O(1.1996^(n(n-1)/2))peggiore dei casi.
Quindi, purtroppo, non ho potuto dimostrare che è in P, o che è NP-completo o NP-difficile. Una cosa certa è che il problema è in NP, ma immagino che questa non sia una sorpresa per nessuno.

Implementazione
Il vantaggio di ridurre questo problema al problema MIS è che il MIS è un problema classico, per il quale è possibile trovare diverse implementazioni e che il problema MIS è anche facilmente scritto come ILP.
Ecco una formulazione ILP del problema 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

A mio avviso, quello dovrebbe essere il modo più efficiente per risolvere questo problema (usando questo modello come problema MIS), dal momento che il risolutore di ILP è incredibilmente efficiente, specialmente quando si tratta di grandi casi.

Questa è un'implementazione che ho fatto usando Python3 e il solutore GLPK . Per testarlo, è necessario un solutore LP compatibile con il formato di file 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')

Puoi quindi risolverli con il glpsolcomando:
glpsol --lp LP_file_1
The aababaaviene risolto rapidamente (0,02 sec sul mio laptop), ma come previsto, le cose diventano (molto) più difficili man mano che la dimensione della stringa aumenta ....
Questo programma fornisce solo il valore numerico (e non la partizione ottimale), tuttavia la partizione ottimale e le sottostringhe corrispondenti possono essere trovate con un'implementazione simile, usando un'interfaccia solutore / python LP come pyomo

Tempo e memoria
aababaa : 0,02 secondi, 0,4 MB, valore: 4
kzshidfiouzh: 1,4 secondi, 3,8 MB, valore: 10
aababababbababab: 60,2 secondi, 31,5 MB, valore: 8
kzshidfiouzhsdjfyu: 207,5 secondi, 55,7 MB, valore: 14
Si noti che il solutore LP offre anche l'attuale limite inferiore e superiore della soluzione, quindi per l'ultimo esempio, ho potuto ottenere la soluzione effettiva come limite inferiore dopo un minuto.


La modellazione non è una riduzione o una prova della complessità, sebbene possa essere utile per implementare soluzioni. Inizialmente ho scritto questo modello (MIS) come commento sotto la risposta principale e successivamente l'ho eliminato. Markus Schmid, uno dei pochi teorici a scrivere articoli su questo argomento, ha già fornito una risposta dettagliata su questa pagina web. La classe di complessità del problema decisionale rimane aperta in letteratura.
גלעד ברקן

In questo caso, MIS è una specie di associazione banale poiché ovviamente stiamo cercando un folto gruppo di cose "connessione (bordo) libera". Con un alfabeto di un carattere, ad esempio, la risposta è una partizione numerica per la quale ci sarebbe una semplice soluzione temporale polinomiale. Potrebbero esserci aspetti del problema che offrono ottimizzazioni che potrebbero eludere un LP basato su O (n ^ 2) a causa di ulteriori ricerche e che verrebbero persi facendo una pausa nella vista MIS. Ma ha un bell'aspetto per una soluzione di lavoro generale.
גלעד ברקן

Hai letto la mia risposta? Offro una banale riduzione del tempo polinomiale a senso unico da MIS a questo problema, non viceversa. Per quanto riguarda l'alfabeto a carattere singolo, il problema è ovviamente in P, con una banale risoluzione banale.
m.raynal,

Sembra che tu abbia formulato ipotesi sulla sua classe di complessità basata su MIS.
גלעד ברקן

Quindi leggi la risposta :-) vedrai che non è il caso, io uso solo la complessità MIS per dare un limite superiore alla complessità del problema. Non un limite inferiore.
m.raynal,

0

La mia altra risposta era strettamente correlata, ma non corrispondeva esattamente a questo problema, lasciando ambiguo il fatto che trovare la più grande fattorizzazione a stringhe senza uguaglianza potesse essere di una classe di complessità diversa rispetto a se esistesse una fattorizzazione senza uguaglianza con lunghezza del fattore legata (quest'ultima essere affrontato dal documento citato).

Nel documento, Pattern matching con variabili: algoritmi veloci e nuovi risultati di durezza (Henning Fernau, Florin Manea, Robert Mercaş e Markus L. Schmid, in Proc. 32 ° Simposio sugli aspetti teorici dell'informatica, STACS 2015, volume 30 di Leibniz International Proceedings in Informatics (LIPIcs) , pagine 302–315, 2015), gli autori mostrano che è NP-completo decidere, per un dato numero ke una parola w, se wpuò essere scomposto in kfattori distinti.

Se consideriamo il commento di templatetypedef , sottintendendo che potrebbe esserci una soluzione temporale polinomiale alla fattorizzazione illimitata e senza eguaglianza, allora sicuramente potremmo usare un tale algoritmo per rispondere se potessimo dividere la stringa in kfattori distinti (sottostringhe) semplicemente osservando se kè meno del massimo che già conosciamo.

Schmid (2016), tuttavia, scrive che "è ancora un problema aperto se MaxEFF-s rimane NP-completo se l'alfabeto è risolto". (Calcolarizzazione di fattorizzazioni di stringhe ripetitive e senza uguaglianza, Volume teorico dell'informatica 618 , 7 marzo 2016, pagine 42-51)

La dimensione massima di fattorizzazione senza uguaglianza (MaxEFF-s) è comunque parametrizzata ed è definita come:

Istanza: Una parola we un numero m, 1 ≤ m ≤ |w|.

Domanda: esiste una fattorizzazione senza uguaglianza p di wwith s(p) ≥ m? ( s(p)essendo la dimensione della fattorizzazione.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.