2008-09-29 13 views
2

Problème:Trouvez la sous-chaîne de préfixe qui donne la meilleure compression

Étant donné une liste de chaînes, trouver la sous-chaîne qui, si elle soustrait depuis le début de toutes les chaînes où il correspond et remplacé par un octet d'échappement, donne la longueur totale la plus courte.

Exemple:

"foo", "fool", "bar"

Le résultat est le suivant: "toto" que la chaîne de base avec les cordes "\0", "\0l", "bar" et une longueur totale de 9 octets. "\0" est l'octet d'échappement. La somme de la longueur des chaînes d'origine est 10, donc dans ce cas, nous avons seulement enregistré un octet.

Un algorithme naïf ressemblerait à ceci:

for string in list 
    for i = 1, i < length of string 
     calculate total length based on prefix of string[0..i] 
     if better than last best, save it 
return the best prefix 

Cela nous donnera la réponse, mais il est quelque chose comme O ((n * m)^2), ce qui est trop cher.

Répondre

6

Utiliser une forêt d'arbres préfixe (TRIE) ...

f_2 b_1 
/  | 
o_2  a_1 
|  | 
o_2  r_1 
| 
l_1 

alors, nous pouvons trouver le meilleur résultat, et garantir, en maximisant (depth * frequency) qui sera remplacé par votre caractère d'échappement. Vous pouvez optimiser la recherche en effectuant une recherche de profondeur de branche et de profondeur en recherchant le maximum.

Sur la complexité: O (C), comme mentionné dans le commentaire, pour le construire, et pour trouver l'optimal, cela dépend. Si vous commandez la fréquence des premiers éléments (O (A) - où A est la taille de l'alphabet des langues), vous pourrez découper plus de branches et avoir de bonnes chances d'obtenir un temps sub-linéaire.

Je pense que c'est clair, je ne vais pas l'écrire - qu'est-ce que c'est un devoir? ;)

+0

Ça sonne bien, même si je pense que vous voudriez ((profondeur - 1) * fréquence), en supposant que la taille du remplacement est égale à celle d'un caractère (bien que la question indique un octet). Doit fonctionner dans O (c) où c est le nombre total de caractères. –

+0

La première partie est essentiellement la construction d'un trie à partir d'une liste de chaînes, soit dit en passant. – Tyler

+0

Haha, non ce n'est pas un devoir. Je suis trop vieux pour ça. =) J'ai une assez bonne implémentation, mais il n'est pas garanti de donner un résultat optimal.Belle idée avec un arbre. –

1

Je voudrais essayer de commencer en triant la liste. Ensuite, vous allez simplement de chaîne en chaîne en comparant le premier caractère au premier caractère de la chaîne suivante. Une fois que vous avez un match, vous regardez le char suivant. Vous auriez besoin de trouver un moyen de suivre le meilleur résultat jusqu'à présent.

+0

Avec cette approche, pouvez-vous garantir que vous aurez une solution optimale? Si vous choisissez toujours le char qui vous donne la plupart des chaînes avec le même préfixe, vous obtenez le préfixe commun le plus long, et ce n'est peut-être pas ce qui donne la meilleure compression. –

+0

Cela dépendrait de la partie sur "Vous auriez besoin de trouver un moyen de suivre le meilleur résultat jusqu'à présent." – EBGreen

1

Eh bien, la première étape serait de trier la liste. Ensuite, on passe à travers la liste, en comparant chaque élément avec le précédent, en gardant la trace des plus longs 2 caractères, 3 caractères, 4 caractères, etc. Alors, les 20 préfixes de 3 caractères sont mieux représentés que les 15 préfixes de 4 caractères.