Je suis tombé sur le problème suivant dans mon ancien manuel d'algorithme tchèque, malheureusement, sans conseils ni solution.
"Nous définissons les mots de Fibonacci comme , F 1 = b , F n + 2 = F n F n + 1 , où a et b sont des lettres générales. Comment dans une chaîne donnée (sur un alphabet potentiellement grand) pouvez-vous trouver le sous-mot de Fibonacci le plus long en temps linéaire? "
Je connais une solution en temps quadratique, mais je ne peux pas la réduire à linéaire. Quelqu'un peut-il m'orienter dans la bonne direction?
Réponses:
Le chemin le plus évident est la programmation dynamique: laissez stocker les deux lettres pour lesquelles un mot d'ordre de Fibonacci i commence à la position j , et calculez cela en regardant F ( i - 2 , j ) et F ( i - 1 , j + fib ( i ) ) . Cela prend au maximum O ( n log n ) , car il n'y a que de nombreuses valeurs logarithmiques possibles de iF( i , j ) je j F( i - 2 , j ) F( i - 1 , j + fib( i ) ) O ( n logn ) je .
Mais je soupçonne qu'il ne peut y avoir que des positions pour lesquelles F ( i - 2 , j ) n'est pas vide (c'est-à-dire que lorsque deux mots Fibonacci de même longueur sont présents, ils ne peuvent se chevaucher que jusqu'à une fraction constante de leur longueur plutôt que la plupart de leur longueur). Les positions non vides de F ( i - 2 , j ) sont les seules pour lesquelles vous devez faire le calcul (à temps constant) pour F ( i , j )O ( n / fib( i ) ) F( i - 2 , j ) F( i - 2 , j ) F( i , j ) . Donc, si ma suspicion est vraie, vous pouvez l'accélérer jusqu'à en gardant une liste de positions non vides pour chaque valeur de i et en utilisant la liste pour i - 2 pour accélérer le calcul de la liste pour i .O ( n ) je i - 2 je
Si vous stockez dans un tableau, l'espace serait toujours O ( n log n ) même après l'accélération, mais cela pourrait être amélioré en utilisant une table de hachage à la place. Ou vous pouvez également stocker F dans un tableau contenant des bits avec O ( n ) log n mots (en utilisant l'observation que vous avez seulement besoin de savoir s'il est vide ou non; vous pouvez trouver les deux caractères pour chaque sous-chaîne en regardant les deux premières de ses positions dans la chaîne d'entrée).F O ( n logn ) F O ( n ) Journaln
la source