Comment fonctionne un dictionnaire T9? Quelle est la structure des données derrière elle. Si nous tapons '4663' nous obtenons 'bien' quand nous appuyons sur le bouton nous sommes 'partis' puis 'à la maison' etc ...
EDIT: Si l'utilisateur tape 46 alors il devrait montrer 'go' et quand on appuie sur la flèche vers le bas devrait montrer 'disparu' etc ...
Il peut être implémenté de plusieurs manières, dont l'une est Trie . L'itinéraire est représenté par les chiffres et les nœuds pointent vers une collection de mots.
Il peut également être implémenté à l'aide de tables de hachage imbriquées, la clé de la table de hachage est une lettre et sur chaque chiffre, l'algorithme calcule toutes les routes possibles (O (3 ^ n) routes).
4663
se traduit par
{G, H, I} {M, N, O} {M, N, O} {D, E, F}
T9 fonctionne en filtrant les possibilités de manière séquentielle en commençant par les premières lettres possibles. Ainsi, la première étape de votre exemple sera de filtrer la liste des dictionnaires sur tous les mots commençant par G, H ou I. Étape suivante, prenez cette liste et filtrez les secondes lettres par M, N, O. Et ainsi de suite ...
Je suppose que, comme ceux d'avant, T9 utilise un trie, où les liens sont représentés par un bitmap (1 bit par lettre). C'est ce qu'on appelle une structure de données succincte, comme l'explique très bien Steve Hanov:
Je pense que T9 utilise un Trie bitmap. Au premier niveau, il y a un mot 32 bits (je suppose qu'ils ont été étendus à 32) où chaque bit représente une lettre. Toutes les lettres qui sont valides comme lettres de départ pour un mot ont leur bit défini.
Au niveau suivant, il existe une carte 32 bits pour chacun de ces bits définis au niveau précédent. Dans ces cartes, chaque bit est défini si la lettre correspondante est valide comme deuxième lettre dans un mot, la lettre de départ étant décidée par le premier niveau.
La structure continue alors. L'utilisation d'un bit par lettre rend le stockage très efficace. Le schéma d'adressage doit cependant être difficile. Il pourrait également y avoir une sorte d'optimisation en utilisant le schéma ci-dessus pour les mots courts tout en utilisant autre chose pour les mots plus longs.
Implémentation C # avec Trie
public interface ICellT9
{
void Add(string a_name);
List<string> GetNames(string a_number);
}
public class Cell : ICellT9
{
private Dictionary<int, Cell> m_nodeHolder;
private List<string> m_nameList;
public Cell()
{
m_nameList = new List<string>();
m_nodeHolder = new Dictionary<int, Cell>();
for (int i = 2; i < 10; i++)
{
m_nodeHolder.Add(i, null);
}
}
public void Add(string a_name)
{
Add(a_name, a_name);
}
private void Add(string a_name, string a_originalName)
{
if (string.IsNullOrEmpty(a_name) &&
(string.IsNullOrEmpty(a_originalName) == false))
{
m_nameList.Add(a_originalName);
}
else
{
int l_firstNumber = CharToNumber(a_name[0].ToString());
if (m_nodeHolder[l_firstNumber] == null)
{
m_nodeHolder[l_firstNumber] = new Cell();
}
m_nodeHolder[l_firstNumber].Add(a_name.Remove(0, 1), a_originalName);
}
}
public List<string> GetNames(string a_number)
{
List<string> l_result = null;
if (string.IsNullOrEmpty(a_number))
{
return l_result;
}
int l_firstNumber = a_number[0] - '0';
if (a_number.Length == 1)
{
l_result = m_nodeHolder[l_firstNumber].m_nameList;
}
else if(m_nodeHolder[l_firstNumber] != null)
{
l_result = m_nodeHolder[l_firstNumber].GetNames(a_number.Remove(0, 1));
}
return l_result;
}
private int CharToNumber(string c)
{
int l_result = 0;
if (c == "a" || c == "b" || c == "c")
{
l_result = 2;
}
else if (c == "d" || c == "e" || c == "f")
{
l_result = 3;
}
else if (c == "g" || c == "h" || c == "i")
{
l_result = 4;
}
else if (c == "j" || c == "k" || c == "l")
{
l_result = 5;
}
else if (c == "m" || c == "n" || c == "o")
{
l_result = 6;
}
else if (c == "p" || c == "q" || c == "r" || c == "s")
{
l_result = 7;
}
else if (c == "t" || c == "u" || c == "v")
{
l_result = 8;
}
else if (c == "w" || c == "x" || c == "y" || c == "z")
{
l_result = 9;
}
return l_result;
}
}
Je le ferais probablement en commençant par un dictionnaire, puis (pour chaque mot) Poussez le mot sur une liste saisie par les nombres qui pourraient former le mot.
Ensuite, vous devrez probablement trier les listes résultantes d'une certaine manière, de sorte que les mots les plus probables apparaissent avant les mots moins probables (si vous avez l'espace, j'inclurais également une petite zone pour un compteur, afin que nous puissions trier ces OR déplacez simplement le dernier utilisé au début de la liste de suggestions, donc nous, avec le temps, tendons à donner à l'utilisateur une meilleure réponse).
De cette façon, lorsque vous avez 4663 en entrée, vous pouvez tout simplement récupérer la liste liée pertinente avec environ O(1) recherche de table de hachage).