Recherche de la sous-séquence répétée la plus longue

9

Étant donné une chaîne , je voudrais trouver la sous-séquence répétée la plus longue (au moins deux fois). Autrement dit, je voudrais trouver une chaîne qui est une sous-séquence (ne doit pas nécessairement être contiguë) de telle que . Autrement dit, w est une chaîne dont les moitiés apparaissent deux fois de suite. Notez que w est une sous-séquence de s , mais pas nécessairement une sous-chaîne.w s w = w w w w sswsw=wwwws

Exemples:

Pour 'ababccabdc', ce sera 'abcabc', car 'abc' = 'abc' et 'abc' apparaît (au moins) deux fois dans 'ababccabdc'.

Pour 'addbacddabcd', une option est 'dddd' parce que 'dd' apparaît deux fois (je ne peux pas utiliser la même lettre plusieurs fois, mais ici j'ai 4 'd's donc c'est ok), mais c'est lebngth 4. Je peux en trouver une meilleure de longueur 8: 'abcdabcd', car 'abcd' est une sous-chaîne de 'addbacddabcd' qui apparaît deux fois.

Je suis intéressé à trouver la sous-séquence répétée la plus longue. Ceci est également appelé "recherche du carré le plus long / le plus grand", mais j'ai lu de nombreux articles dans lesquels un carré est défini pour une sous-chaîne et non pour une sous-séquence.

Je peux facilement utiliser un algorithme de force brute qui prendra en itérant sur toutes les options pour un point d'arrêt dans la chaîne, puis j'aurai deux chaînes dans lesquelles je rechercherai la sous-séquence commune la plus longue / la plus longue, mais chaque vérification prendra utilisant une technique de programmation dynamique, donc tout le temps sera . J'ai trouvé un algorithme plus efficace pour la sous-séquence commune la plus longue qui prend O (\ frac {n ^ 2} {\ log n}) , donc le temps d'exécution sera O (\ frac {n ^ 3} {\ log n}) .O ( n 2 ) O ( n 3 )O(n3)O(n2)O(n3)O(n3O(n2logn)O(n3logn)

Je recherche un algorithme plus efficace pour le problème de sous-séquence répétitif le plus long. Peut-être que mon idée d'itérer sur tous les points d'arrêt fait perdre trop de temps et peut être réduite à moins d'itérations. Ou peut-être qu'un algorithme avec une attitude différente peut résoudre ce problème.

J'ai cherché dans de nombreuses revues et questions précédentes, et la plupart des résultats que j'ai trouvés concernaient une sous-chaîne et non une sous-séquence.

J'ai également lu que cela peut être fait en utilisant des arbres de suffixes, mais cela était également pertinent pour les sous-chaînes et je ne suis pas sûr si une telle idée peut être étendue pour la sous-séquence.

Je recherche une solution qui s'exécute dans le temps . S'il existe un dans le temps ce sera encore mieux (je ne suis pas sûr que cela existe).O ( n log n )O(n2)O(nlogn)

Dan D-man
la source
4
Recherchez des arbres de suffixe ou des tableaux de suffixes.
Pseudonyme
1
Il est très peu probable qu'un algorithme existe pour ce problème, car s'il le faisait, vous pourriez l'utiliser pour battre l'algorithme le plus connu pour trouver le LCS de deux chaînes de longueur et comme suit: Formez la chaîne , où est copies d'un caractère qui n'apparaît pas dans ou , puis exécutez votre algorithme de temps dessus. Les deux «moitiés» de la sous-séquence répétée la plus longue commenceront nécessairement par , donc la moitié vient de chacun de etn u v x u x v x n + 1 u v o ( n 2 ) x u vo(n2)nuvxuxvxn+1$uvo(n2)xuv, résoudre le problème LCS.
j_random_hacker
@j_random_hacker LCS peut être résolu dans aide de l'arborescence de suffixes ou dans aide de hachages roulants. O ( n log n )O(n+m)O(nJournaln)
Evil
@Evil: Je ne vois pas encore comment, pourriez-vous donner un peu plus de détails? (Êtes-vous sûr que vous ne pensez pas à la chaîne Sub la plus longue commune , qui peut être résolue dans ces complexités temporelles?)
j_random_hacker
@j_random_hacker Je pensais que vous compariez le visé avec le LCS (consécutif), mais ici, comme vous l'avez mentionné, oui, je n'ai même pas vu de solution de travail dans n ^ 2 pour la plus longue conséquence commune (j'ai trouvé un code de programmation dynamique, propagé sur de nombreuses pages, qui est imparfait, semblable à la réponse votée). Donc, j'ai simplement mal compris votre commentaire, désolé. o(n2)
Evil

Réponses:

-1

Voici une solution de programmation dynamique.

Supposons que la chaîne d'entrée soit . Créez une table dont les lignes et les colonnes sont indexées par (où est la longueur de la chaîne), remplies par la règle La réponse est . T 0 , , n n T [ i , j ] = { 0 si  i = 0  ou  j = 0 , T [ i - 1 , j - 1 ] + 1 si  x i = x j  et  i j , max ( T [ i - 1x1xnT0,,nn

T[i,j]={0if i=0 or j=0,T[i1,j1]+1if xi=xj and ij,max(T[je-1,j],T[je,j-1])autrement.
T[n,n]
jir17
la source
Supposons que nous soyons à un avec , et que la condition dans votre énoncé soit vraie. Ensuite , implique que le caractère à la position fait partie des deux sous- séquences. i = j + 1 i - 1 = jje,jje=j+1ifdp[i][j] = dp[i - 1][j - 1] + 1je-1=j
j_random_hacker
3
Bienvenue en informatique! Veuillez vous débarrasser du code source et le remplacer par des idées, un pseudo code et des arguments de justesse. Voir ici et ici pour les méta discussions connexes.
Raphael
@Raphael Une formule récursive ne compte pas comme code source.
Number945
1
@BreakingBenjamin Selon la langue de votre choix, vous pouvez écrire la récurrence donnée plus ou moins littéralement. Le fait est qu'il n'y a aucune explication ici.
Raphael