Número máximo de subcadenas únicas de una partición

30

Modifiqué el título para que sea más comprensible.

Aquí hay una versión detallada de la pregunta:

Tenemos una cadena s y queremos dividirla en subcadenas . Cada subcadena es diferente entre sí. ¿Cuál es el número máximo de subcadenas únicas que podemos tener de un corte? En otras palabras, ¿cuál es el número máximo de subcadenas únicas que se concatenan para formar s?

Aquí hay unos ejemplos:

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 : ssolo contiene caracteres en minúscula. No se me dice cuánto tiempo sy, por lo tanto, no puedo adivinar la complejidad óptima del tiempo. :(

¿Es un problema NP-difícil? Si no, ¿cómo puedo resolverlo de manera eficiente?

Escuché este problema de uno de mis amigos y no pude responderlo. Estoy tratando de usar un Trie + codicioso para resolver este problema. El método falla para el primer ejemplo.

Aquí está la solución Trie que se me ocurrió:

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

Por ejemplo 1, el código anterior devolverá 3 ya que está intentando dividirse sen a|ab|abaa.

Agregar: Gracias a la idea de todos, parece que este problema está muy cerca de un problema de NP. En este momento, estoy tratando de pensarlo desde esta dirección. Supongamos que tenemos una función Guess(n). Esta función volverá Truesi pudiéramos encontrar nsubcadenas únicas de una división o de Falseotra manera. Una observación aquí es que si Guess(n) == True, entonces Guess(i) == Truepara todos i <= n. Ya que podemos fusionar dos subcadenas adyacentes juntas. Esta observación puede conducir a una solución binaria. Sin embargo, todavía requiere que podamos calcular la Guessfunción de manera muy eficiente. Lamentablemente, todavía no pude encontrar una forma polinómica para calcular Guess(n).

wqm1800
fuente
El primero también se puede dividir, ya aab|a|b|aaque todavía es 4
smac89
3
Por curiosidad, ¿cuánto tiempo pueden durar tus hilos?
templatetypedef
aababaa se puede dividir en a | aa | aab | aaba | aabab | aababa | aba | ... etc. ¿Cómo conseguiste solo 4?
Suraj Motaparthy el
La cadena solo contiene ao b?
Pham Trung el
@PhamTrung No, pero puede suponer que solo contiene caracteres en minúscula.
wqm1800

Respuestas:

15

Esto se conoce como el problema de partición de cuerdas con detección de colisión y se demuestra que se completa NP mediante una reducción de 3-SAT en un documento de Anne Condon, Ján Maňuch y Chris Thachuk - Complejidad de un problema de partición de cuerda con detección de colisión y su relación con el diseño del oligo para la síntesis génica ( International Computing and Combinatorics Conference , 265-275, 2008).

גלעד ברקן
fuente
Eché un vistazo superficial a ese documento, y parece que el resultado demuestra que solo muestra que este problema es NP-difícil en el caso de que haya un límite superior para el número de caracteres que puede haber en cada subcadena. ¿Es eso exacto? Si es así, eso lo hace un poco diferente a este problema. Razonando por analogía, encontrar un MST se puede hacer en tiempo polinómico aunque el problema de "encontrar un MST sujeto a una restricción de grado en los nodos en el árbol" es NP-difícil.
templatetypedef
1
Para mostrar que este problema es NP-hard, debemos ser capaces de reducir el problema conocido de NP-hard (partición k) a este problema (partición sin restricciones), en lugar de al revés. Un solucionador para la partición k definitivamente puede resolver este problema, pero eso no prueba la dureza NP.
templatetypedef
No veo que el documento resuelva el problema: según tengo entendido, el documento trata sobre el problema de decisión si existe una partición en subcadenas de más de k de longitud. Si k es mayor que la mitad de la longitud total de la cadena, ese problema de decisión es trivialmente verdadero (según tengo entendido).
Hans Olsson el
No, el hecho de que el problema tenga una solución trivial para k grande no significa que k tenga que ser pequeño y que la reducción funcione.
templatetypedef
8

(Muchas gracias a Gilad Barkan (גלעד ברקן) por informarme sobre esta discusión).

Permítanme compartir mis pensamientos sobre este problema desde un punto de vista puramente teórico (tenga en cuenta que también uso "factor" en lugar de "subword").

Creo que una definición suficientemente formal del problema (o problemas) considerada aquí es la siguiente:

Dada una palabra w, encuentre las palabras u_1, u_2, ..., u_k de modo que

  • u_i! = u_j para cada i, j con 1 <= i <j <= k y
  • u_1 u_2 ... u_k = w

Variante de maximización (queremos muchos u_i): maximizar k

Variante de minimización (queremos corto u_i): minimizar max {| u_i | : 1 <= i <= k}

Estos problemas se convierten en problemas de decisión al dar además un límite B, que, de acuerdo con si estamos hablando de la variable "muchos factores" o de la variable "factores cortos", es un límite inferior en k (queremos al menos B factores), o un límite superior en max {| u_i | : 1 <= i <= k} (queremos factores de longitud como máximo B), respectivamente. Para hablar sobre la dureza NP, necesitamos hablar sobre problemas de decisión.

Usemos los términos SF para la variable "factores cortos" y MF para la variable "muchos factores". En particular, y este es un punto realmente crucial, los problemas se definen de tal manera que obtenemos una palabra sobre algún alfabeto que no está restringido de ninguna manera. La versión del problema es que sabemos a priori que solo recibimos palabras de entrada, por ejemplo, el alfabeto {a, b, c, d} es un problema diferente. La dureza NP no se transfiere automáticamente de la variante "sin restricciones" a la "alfabeto fijo" (esta última podría ser más simple).

Tanto SF como MF son problemas NP-completos. Esto se ha demostrado en [1, 1b] y [2], respectivamente (como Gilad ya ha señalado). Si entiendo la definición de problema informal (quizás también) aquí al comienzo de esta discusión correctamente, entonces el problema de esta discusión es exactamente el problema MF. Inicialmente no se menciona que las palabras están restringidas para provenir de un alfabeto fijo, luego se dice que podemos suponer que solo se usan letras minúsculas. Si esto significa que solo consideramos palabras sobre el alfabeto fijo {a, b, c, ..., z}, entonces esto realmente cambiaría mucho en términos de dureza NP.

Una mirada más cercana revela algunas diferencias en la complejidad de SF y MF:

  1. el artículo [1, 1b] muestra que SF sigue siendo NP-completo si fijamos el alfabeto en uno binario (más precisamente: si se obtiene una palabra w sobre las letras a y by un B, ¿podemos factorizarla en distintos factores de longitud en más B?).
  2. El artículo [1, 1b] muestra que SF sigue siendo NP completo si arreglamos el límite B = 2 (más precisamente: obteniendo una palabra w, ¿podemos factorizarla en distintos factores de longitud como máximo 2?).
  3. El documento [3] muestra que si tanto el alfabeto como el B unido están fijos, entonces SF puede resolverse en tiempo polinómico.
  4. El documento [2] muestra que MF es NP-completo, ¡pero solo si el alfabeto no está restringido o fijado a priori! En particular, no responde la pregunta si el problema es NP-completo si solo consideramos las palabras de entrada sobre algún alfabeto fijo (como es habitual en casos prácticos).
  5. El artículo [3] muestra que MF se puede resolver en tiempo polinomial si los límites de entrada B están nuevamente limitados por alguna constante, es decir, la entrada del problema es una palabra y un límite B de {1, 2, ..., K} , donde K es una constante fija.

Algunos comentarios sobre estos resultados: Wrt (1) y (2), es intuitivamente claro que si el alfabeto es binario, entonces, para dificultar el problema SF, el límite B no se puede arreglar también. Por el contrario, corregir B ​​= 2 significa que el tamaño del alfabeto debe ser bastante grande para producir instancias difíciles. Como consecuencia, (3) es bastante trivial (de hecho, [3] dice un poco más: luego podemos resolverlo en tiempo de ejecución no solo polinomial, sino también | w | ^ 2 veces un factor que solo depende del tamaño del alfabeto y obligado B). (5) tampoco es difícil: si nuestra palabra es larga en comparación con B, entonces podemos obtener la factorización deseada simplemente dividiéndonos en factores de diferentes longitudes. Si no es así, entonces podemos aplicar la fuerza bruta a todas las posibilidades, que es exponencial solo en B, que en este caso se supone que es una constante.

Entonces, la imagen que tenemos es la siguiente: SF parece más difícil, porque tenemos dureza incluso para alfabetos fijos o para un límite fijo B. El problema MF, por otro lado, se resuelve en el tiempo polivinílico si el límite es fijo (en esto es más fácil que SF), mientras que la pregunta correspondiente es el tamaño del alfabeto abierto. Por lo tanto, MF es un poco menos complejo que SF, incluso si resulta que MF para alfabetos fijos también es NP completo. Sin embargo, si se puede demostrar que MF se puede resolver para alfabetos fijos en tiempo múltiple, entonces se muestra que MF es mucho más fácil que SF ... porque el único caso para el que es difícil es algo artificial (¡alfabeto sin límites!) .

Hice un esfuerzo para tratar de resolver el caso de MF con alfabeto limitado, pero no pude resolverlo y desde entonces dejé de trabajar en él. No creo que otros investigadores hayan intentado mucho resolverlo (por lo que este no es uno de estos problemas abiertos muy difíciles, muchas personas ya lo han intentado y han fallado; lo considero factible de alguna manera). Supongo que también es NP-hard para alfabetos fijos, pero tal vez la reducción es tan complicada que obtendrías algo como "MF es difícil para alfabetos de tamaño 35 o mayor" o algo así, que tampoco sería súper agradable .

Con respecto a la literatura adicional, conozco el artículo [4], que considera el problema de dividir una palabra w en factores distintos u_1, u_2, ..., u_k que son todos palíndromos, que también es NP-completo.

Eché un vistazo rápido al papel [5], señalado por Gilad. Sin embargo, parece considerar una configuración diferente. En este artículo, los autores están interesados ​​en la pregunta combinatoria de cuántas subsecuencias o subpalabras distintas pueden estar contenidas en una palabra determinada, pero estas pueden superponerse. Por ejemplo, aaabaab contiene 20 subpalabras diferentes a, b, aa, ab, ba, bb, aaa, aab, aba, baa, aaab, aaba, abaa, baab, aaaba, aabaa, abaab, aabaab, aaabaa, aaabaab (tal vez yo mal contado, pero entiendes la idea). Algunos de ellos tienen solo una ocurrencia, como baa, algunos de ellos varios, como aa. En cualquier caso, la pregunta no es cómo podemos dividir la palabra de alguna manera para obtener muchos factores distintos, ya que esto significa que cada símbolo individual contribuye exactamente a un factor.

Con respecto a las soluciones prácticas para este tipo de problemas (tenga en cuenta que soy un teórico, así que tómelo con gran detalle):

  • Que yo sepa, no hay límites inferiores teóricos (como la dureza NP) que descartarían resolver MF en tiempo polinómico si consideramos solo palabras de entrada sobre un alfabeto fijo. Sin embargo, hay una advertencia: si obtienes un algoritmo de poli-tiempo, ¡esto debería ejecutarse exponencialmente en el número de símbolos del alfabeto fijo (o exponencial en alguna función de eso)! De lo contrario, también sería un algoritmo de tiempo polinómico para el caso de alfabetos no acotados. Entonces, como teórico, estaría buscando tareas algorítmicas que se puedan calcular en tiempo exponencial solo si el número de símbolos y que de alguna manera ayudan a diseñar un algoritmo para MF. Por otro lado, es probable que dicho algoritmo no exista y MF también sea NP-hard en el caso del alfabeto fijo.

  • Si está interesado en soluciones prácticas, puede ser útil aproximar la solución. Por lo tanto, obtener la factorización que se garantiza que sea solo la mitad del óptimo en el peor de los casos no sería tan malo.

  • Supongo que las heurísticas que no ofrecen una relación de aproximación demostrable, pero funcionan bien en un entorno práctico también serían interesantes.

  • Transformar las instancias problemáticas en instancias SAT o ILP no debería ser demasiado difícil y luego podría ejecutar un SAT o ILP-Solver para incluso obtener soluciones óptimas.

  • Mi opinión personal es que, aunque no se sabe si el caso del alfabeto fijo de MF es NP-hard, hay suficientes conocimientos teóricos que sugieren que el problema es lo suficientemente difícil como para justificar la búsqueda de soluciones heurísticas, etc. funcionan bien en un entorno práctico.


Bibliografía:

[1] Anne Condon, Ján Manuch, Chris Thachuk: La complejidad de la partición de cuerdas. J. Algoritmos discretos 32: 24-43 (2015)

[1b] Anne Condon, Ján Manuch, Chris Thachuk: Complejidad de un problema de partición de cuerdas consciente de colisión y su relación con el diseño de Oligo para la síntesis génica. COCOON 2008: 265-275

[2] Henning Fernau, Florin Manea, Robert Mercas, Markus L. Schmid: coincidencia de patrones con variables: algoritmos rápidos y nuevos resultados de dureza. STACS 2015: 302-315

[3] Markus L. Schmid: Computación de factorizaciones de cuerdas repetitivas y sin igualdad. 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 factorización palindrómica diversa es NP-completa. En t. J. encontrado. Comput Sci. 29 (2): 143-164 (2018)

[5] Abraham Flaxman, Aram Wettroth Harrow, Gregory B. Sorkin: Cuerdas con muchas subsecuencias y subcadenas distintas. Electr. J. Comb. 11 (1) (2004)

Markus L. Schmid
fuente
(¡Por cierto, gracias por publicar!) Solo para aclarar, mi comentario anterior sobre la referencia [5], en realidad era sobre una pregunta diferente: era una respuesta a la pregunta de LukStorms en la sección de comentarios principal , "Para cualquier cadena de N longitud de P posibles caracteres, ¿cuál es el máximo de subcadenas únicas que podrían contener tales cadenas?
עדלעד ברקן
3

Aquí hay una solución, pero explota muy rápido y no está cerca de una solución eficiente. Primero divide la cadena en una lista de subcadenas únicas sin preocuparse por ordenar, luego intenta usar itertools.permutation para volver a ensamblar esas subcadenas en la cadena original, probando CADA permutación para ver si coincide con la cadena original.

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

Para la primera prueba obtenemos esto:

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

Quizás esto se pueda optimizar de alguna manera, pero eso lleva unos segundos en esta máquina.

neutrino_logic
fuente
3

He probado este problema y lo he pensado en términos o si se debe hacer una partición en un índice determinado. Entonces, esta función es recursiva y crea 2 ramas en cada índice 1. No particione en el índice i 2. Partición en el índice i.

Basado en la partición, completo un conjunto y luego devuelvo el tamaño del conjunto

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

Ravi Chandak
fuente
¡Gracias por tu solución! Esta solución DFS es muy clara. Tengo una pequeña sugerencia que podría acelerar la keepfunción ya que la set.copy()función consume mucho tiempo. ¿Qué hay de usar el backtracking que es cuando finaliza esta pila de funciones, elimina el candidato actual del conjunto?
wqm1800
@ wqm1800 ¿pueden dar más detalles? Lo siento, no entiendo exactamente. Incluso si usamos el backtrack, todavía tenemos que mergeseparar los conjuntos ya que siempre estamos bifurcando. Por lo tanto, ya sea fusionando o copiando. ¿Puedes elaborar?
Ravi Chandak
1
Aquí está mi solución de retroceso . Esto podría funcionar porque la pila de funciones se ejecuta como DFS, por lo que cuando finaliza la función, significa que ha terminado de buscar en todos los subconjuntos.
wqm1800
3

Puede utilizar una función recursiva con un conjunto como segundo parámetro para realizar un seguimiento de las cadenas únicas en la ruta actual hasta el momento. Para cada recursión, repita todos los índices más 1 para dividir la cadena para una posible cadena candidata, y si la cadena candidata aún no está en el conjunto, realice una llamada recursiva con la cadena restante y el candidato agregado al conjunto Para obtener el número máximo de subcadenas únicas de la cadena restante, agregue 1 y devuelva el máximo de los máximos de las iteraciones. Devuelve 0 si la cadena dada está vacía o si todas las cadenas candidatas ya están en el conjunto:

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

Demostración: https://repl.it/@blhsing/PriceyScalySphere

En Python 3.8, la lógica anterior también se puede escribir con una llamada a la maxfunción con una expresión generadora que filtra los candidatos que se han "visto" con una expresión de asignació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)
blhsing
fuente
1

Aquí hay una respuesta basada en la teoría de grafos.

Modelado
Este problema se puede modelar como un problema de conjunto independiente máximo en un gráfico de tamaño de la O(n²)siguiente manera:
Sea w = c_1, ..., c_nla cadena de entrada.
Vamos a G = (V,E)ser un grafo no dirigido, construido de la siguiente manera:
V = { (a, b) such that a,b in [1, n], a <= b }. Podemos ver que el tamaño de Ves n(n-1)/2, donde cada vértice representa una subcadena de w.
Luego, por cada par de vértices (a1, b1)y (a2, b2), construimos el borde ((a1, b1), (a2, b2))si
f (i) se [a1, b1]cruza [a2, b2]o
(ii) c_a1...c_b1 = c_a2...c_b2.
Dicho de otro modo, construimos un borde entre dos vértices si (i) las subcadenas en las que representan se superponen wo (ii) las dos subcadenas son iguales.

Entonces podemos ver por qué un máximo conjunto independiente de Gproporciona la respuesta a nuestro problema.

Complejidad
En el caso general, el problema del conjunto independiente máximo (MIS) es NP-duro, con una complejidad temporal O(1.1996^n)y en el espacio polinomial [Xiao, NamaGoshi (2017)] .
Al principio pensé que el gráfico resultante sería un gráfico cordal (sin ciclo inducido de longitud> 3), lo que habría sido muy bueno desde entonces, el problema MIS se puede resolver en tiempo lineal en esta clase de gráficos.
Pero rápidamente me di cuenta de que no es el caso, es bastante fácil encontrar ejemplos donde hay ciclos inducidos de longitud 5 y más.
En realidad, el gráfico resultante no exhibe ninguna propiedad 'agradable' que generalmente buscamos y que permite reducir la complejidad del problema MIS a uno polinómico.
Esto es solo un límite superior en la complejidad del problema, ya que la reducción del tiempo polinomial va solo en una dirección (podemos reducir este problema al problema MIS, pero no al revés, al menos no trivialmente). Así que finalmente terminamos resolviendo este problema O(1.1996^(n(n-1)/2))en el peor de los casos.
Entonces, por desgracia, no pude demostrar que está en P, o que es NP completo o NP-duro. Una cosa segura es que el problema está en NP, pero supongo que esto no es una sorpresa para nadie.

Implementación
La ventaja de reducir este problema al problema MIS es que el MIS es un problema clásico, para el cual se pueden encontrar varias implementaciones, y que el problema MIS también se escribe fácilmente como un ILP.
Aquí hay una formulación 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

En mi opinión, esa debería ser la forma más eficiente de resolver este problema (usando este modelado como un problema MIS), ya que el solucionador de ILP es increíblemente eficiente, especialmente cuando se trata de grandes instancias.

Esta es una implementación que hice usando Python3 y el solucionador GLPK . Para probarlo, necesita un solucionador de LP compatible con el formato de archivo 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')

A continuación, puede solucionarlo con la glpsolorden:
glpsol --lp LP_file_1
El aababaase resolvió rápidamente (0,02 seg en mi portátil), pero como era de esperar, las cosas se ponen (mucho) más dura como el tamaño de la cadena crece ....
Este programa sólo da el valor numérico (y no la partición óptima), sin embargo, la partición óptima y las subcadenas correspondientes se pueden encontrar con una implementación similar, utilizando una interfaz LP solver / python como pyomo

Tiempo y memoria
aababaa : 0.02 segundos, 0.4 MB, valor: 4
kzshidfiouzh: 1.4 segundos, 3.8 MB, valor: 10
aababababbababab: 60.2 segundos, 31.5 MB, valor: 8
kzshidfiouzhsdjfyu: 207.5 segundos, 55.7 MB, valor: 14
Tenga en cuenta que el solucionador de LP también ofrece los límites inferior y superior actuales en la solución, por lo que para el último ejemplo, podría obtener la solución real como límite inferior después de un minuto.

m.raynal
fuente
El modelado no es una reducción o prueba de complejidad, aunque puede ser útil para implementar soluciones. Originalmente escribí este mismo modelo (MIS) como un comentario debajo de la respuesta principal y luego lo eliminé. Markus Schmid, uno de los pocos teóricos que escribió artículos sobre este tema, ya contribuyó con una respuesta detallada en esta página web. La clase de complejidad del problema de decisión permanece abierta en la literatura.
עדלעד ברקן
En este caso, MIS es una especie de asociación trivial ya que, por supuesto, estamos buscando un gran grupo de cosas "libres de conexión". Con un alfabeto de un carácter, por ejemplo, la respuesta es una partición numérica para la que habría una solución de tiempo polinomial simple. Puede haber aspectos del problema que ofrezcan optimizaciones que podrían eludir un LP basado en O (n ^ 2) si se da más investigación, y se perderían al detenerse en la vista MIS. Pero se ve genial para una solución de trabajo general.
עדלעד ברקן
¿Leíste mi respuesta? Ofrezco una reducción trivial de tiempo polinomial unidireccional de MIS a este problema, no al revés. En cuanto al alfabeto de un solo carácter, el problema está obviamente en P, con una resolución trivial codiciosa.
m.raynal
Parecía que hiciste suposiciones sobre su clase de complejidad basada en MIS.
עדלעד ברקן
Entonces lea la respuesta :-) verá que no es el caso, solo uso la complejidad MIS para dar un límite superior a la complejidad del problema. No es un límite inferior.
m.raynal
0

Mi otra respuesta estaba estrechamente relacionada, pero no correspondía exactamente a este problema, dejando ambiguo si encontrar la factorización de cuerdas libre de igualdad más grande podría ser de una clase de complejidad diferente a si existe alguna factorización libre de igualdad con longitud de factor enlazado (este último siendo abordado por el documento citado).

En el documento, Coincidencia de patrones con variables: Algoritmos rápidos y nuevos resultados de dureza (Henning Fernau, Florin Manea, Robert Mercaş y Markus L. Schmid, en Proc. 32º Simposio sobre aspectos teóricos de la informática, STACS 2015, volumen 30 de Leibniz International Proceedings in Informatics (LIPIcs) , páginas 302–315, 2015), los autores muestran que es NP completo para decidir, para un número dado ky una palabra w, si wse puede factorizar en kfactores distintos.

Si consideramos el comentario de templatetypedef , lo que implica que podría haber una solución de tiempo polinomial para la factorización libre de igualdad más grande y sin restricciones, entonces seguramente podríamos usar dicho algoritmo para responder si pudiéramos dividir la cadena en kfactores distintos (subcadenas) simplemente observando si kes menos del máximo que ya conocemos.

Schmid (2016), sin embargo, escribe que "todavía es un problema abierto si MaxEFF-s permanece NP-completo si el alfabeto es fijo". (Cálculo de factorizaciones de cuerdas repetitivas y sin igualdad, Theoretical Computer Science Volume 618 , 7 de marzo de 2016, páginas 42-51)

Sin embargo, el tamaño máximo de factorización libre de igualdad (MaxEFF-s) todavía está parametrizado y se define como:

Instancia: Una palabra wy un número m, 1 ≤ m ≤ |w|.

Pregunta: ¿Existe una factorización libre de igualdad p de wcon s(p) ≥ m? ( s(p)siendo el tamaño de la factorización).

גלעד ברקן
fuente