33 votes

Analyse de la chaîne

Étant donné une séquence d'opérations:

a*b*a*b*a*a*b*a*b

est-il un moyen de trouver la meilleure de la subdivision de permettre reusage de sous-chaîne.

faire

a*b*a*b*a*a*b*a*b => c*a*c, où c = a*b*a*b

et alors, voyant que

a*b*a*b => d*d, où d = a*b

tous en tous en réduisant les 8 premiers temps de l'exploitation dans les 4 décrit ici?

(c = d = a*b)* * d)*a*c

L'objectif du cours est de minimiser le nombre d'opérations

Je suis en train d'étudier un suffixtree de toutes sortes.

Je suis particulièrement intéressé dans le temps linéaire des heuristiques ou des solutions. Le " * " les opérations sont en fait la matrice de multiplications.

19voto

Nick Fortescue Points 18829

Ce problème est connu comme "Commune de la sous-expression de l'Élimination" ou CST. C'est une version légèrement plus petite de la le problème appelé "Graphe de Réduction" rencontrées par le maître d'œuvre de compilateurs pour les langages de programmation fonctionnelle. Googler "Commune de la sous-expression de l'élimination de l'algorithme" donne beaucoup de solutions, mais aucun que je peux voir, surtout pour les contraintes donné par la multiplication de matrices.

Les pages liées pour donner beaucoup de références.

Mon ancienne réponse est ci-dessous. Cependant, après avoir étudié un peu plus, la solution est tout simplement la construction d'un suffixe de l'arbre. Cela peut être fait en O(N) temps (beaucoup de références sur la page de wikipedia). Ayant fait cela, le sous-expressions (c, d etc. dans votre question) sont des nœuds dans le suffixe de l'arbre - il suffit de les sortir.


Cependant, je pense que MarcoS est à quelque chose avec la suggestion de la plus Longue répétition de sous-Chaîne, comme le graphique de réduction de la priorité pourrait ne pas permettre des optimisations qui peuvent y être autorisé.

esquisse de l'algorithme:

optimise(s):
    let sub = longestRepeatingSubstring(s).
    optimisedSub = optimise(sub)
    return s with sub replaced by optimisedSub

Chaque exécution de la plus longue répétition de sous-chaîne prend du temps N. Vous pouvez probablement utiliser de nouveau le suffixe de l'arbre que vous construire à régler l'ensemble de la chose dans le temps N.

14voto

ninjagecko Points 25709

edit: Les ordres de la croissance dans cette réponse sont nécessaires, en plus de la accepté de répondre dans l'ordre à exécuter le CST ou la matrice de la chaîne de multiplication

Fait intéressant, un algorithme de compression peut être ce que vous voulez: un algorithme de compression vise à réduire la taille de ce qu'il se comprime, et si la seule façon de le faire, c'est la substitution, vous pouvez le tracer et d'obtenir les sous-composants de votre algorithme. Cela peut ne pas donner de bons résultats, bien que pour de petites entrées.

Ce sous-ensembles de vos opérations sont commutatives sera un facteur important dans le choix d'un tel algorithme. [edit: OP dit pas opérations sont commutatives dans sa situation]

Nous pouvons aussi définir une solution optimale, si l'on ignore les effets tels que la mise en cache:

input: [some product of matrices to compute]

given that multiplying two NxN matrices is O(N^2.376)
given we can visualize the product as follows:
    [[AxB][BxC][CxD][DxE]...]
we must for example perform O(max(A,B,C)^2.376) or so operations in order to combine
    [AxB][BxC] -> [AxC]

The max(...) is an estimate based on how fast it is to multiply two square matrices;
a better estimate of cost(A,B,C) for multiplying an AxB * BxC matrix can be gotten 
from actually looking at the algorithm, or running benchmarks if you don't know the
algorithm used.

However note that multiplying the same matrix with itself, i.e. calculating
a power, can be much more efficient, and we also need to take that into account.
At worst, it takes log_2(power) multiplies each of O(N^2.376), but this could be
made more efficient by diagonalizing the matrix first.

Il y a la question de savoir si une approche gourmande est faisable pour pas: si l'on DOIT compresser répétition de sous-chaînes à chaque étape. Cela peut ne pas être le cas, par exemple,

aaaaabaab
compressing 'aa' results in ccabcb and compressing 'aab' is now impossible

Toutefois, j'ai un pressentiment que, si nous essayons de tous les ordres de la compression des sous-chaînes, nous allons probablement pas dans cette question trop souvent.

Ainsi, après avoir écrit ce que nous voulons (les coûts) et considérés comme possiblement questions, nous avons déjà une force brute de l'algorithme qui peut faire cela, et il sera exécuté pour un très petit nombre de matrices:

# pseudocode

def compress(problem, substring)
    x = new Problem(problem)
    x.string.replaceall(substring, newsymbol)
    x.subcomputations += Subcomputation(newsymbol=substring)

def bestCompression(problem)
    candidateCompressions = [compress(problem,substring) for each substring in problem.string]
    # etc., recursively return problem with minimum cost
    # dynamic programming may help make this more efficient, but one must watch
    #   out for the note above, how it may be hard to be greedy

Remarque: selon une autre réponse par Asgeir, ceci est connu comme la Matrice de la Chaîne d'Multiplication problème d'optimisation. Nick Fortescue notes c'est connu aussi, plus généralement, comme http://en.wikipedia.org/wiki/Common_subexpression_elimination -- ainsi, on pourrait trouver un médicament générique du CST ou la Matrice de la Chaîne d'-algorithme de Multiplication/bibliothèque de la littérature, et de brancher le coût des ordres de grandeur je l'ai mentionné plus tôt (vous aurez besoin de ces nomatter la solution que vous utilisez). Notez que le coût des calculs ci-dessus (multiplication, puissance, etc.) supposons qu'ils sont fait de manière efficace avec l'état-of-the-art des algorithmes; si ce n'est pas le cas, remplacer les exposants avec les valeurs appropriées qui correspondent à la manière dont les opérations seront effectuées.

9voto

Asgeir Points 814

Si vous voulez utiliser le moins d'opérations arithmétiques, vous devriez jeter un coup d'œil à la multiplication de chaînes matricielles qui peut être réduite à O (n log n)

8voto

LiKao Points 4825

Depuis le sommet de la tête, le problème semble NP pour moi. Selon les substitutions que vous faites d'autres changements seront possible ou impossible par exemple pour la chaîne d*e*a*b*c*d*e*a*b*c*d*e*a il y a plusieurs possibilités.

Si vous prenez la plus longue de la commune de chaîne, ce sera: f = d*e*a*b*c et il est possible de substituer f*f*e*a vous laissant avec trois multiplications à la fin, et quatre intermédiaires (total de sept).

Si vous au lieu de substitut de la façon suivante: f = d*e*a vous obtenez f*b*c*f*b*c*f qui vous pouvez remplacer l'aide d' g = f*b*cde g*g*f , pour un total de six multiplication.

Il y a d'autres substitutions dans ce problème, mais je n'ai pas le temps de les compter tous maintenant.

Je suppose que pour une complète minimale de substitution, il est non seulement nécessaire pour déterminer la plus longue sous-chaîne commune, mais aussi le nombre de fois que chaque sous-chaîne répète, ce qui signifie probablement que vous avez un suivi de toutes les substitutions de si loin et de faire des retours en arrière. Néanmoins, il pourrait être plus rapide que les multiplications.

7voto

MarcoS Points 7305

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X