T9IME,名字聽起來陌生,可是大家卻經常使用它。可以說T9IME是IME曆史中的一次革命。至少自T9IME開始,IME有長足的進步。
手機中九個數字鍵。26個英文字母被分配到2至9這8個數字鍵上。以前想輸入英文單詞的時候總是需要連續多次按某個鍵,才能得到目標字母。比如想輸入“hello”,就需要按兩次4,兩次3,三次5,三次5,三次6.輸入一個單詞需要數十次的按鍵,更何況還有經常按錯的情況。編輯一條簡訊非常麻煩。
T9IME很好的解決了這一問題。使用者利用9個數字鍵輸入非常雜的英文單詞並且不用重複按某個字元。系統將會根據已有詞庫找出可能性最大的單詞。例如,目標單詞為“hello”,只需輸入4,3,5,5,6即可,系統會自動過濾掉不合法的單詞如“gdjjm”。排除非法單詞,只考慮合法單詞,這樣大大加速了輸入速度。
然而這隻是第一步,因為每次輸入數字之後,可能有多個候選單詞首碼與此匹配。這就需要按可能性提供可能性最大的(最常用)的英文單詞。比如系統已知兩個單詞:"idea","hello"。idea最常用(可能度最高)。那麼當依次輸入4,3,5,5,6時,對於每次按鍵系統給出的候選單詞應該是:
i (4)
id (3)
hel (5)
hell (5)
hello (6)
這樣的話,通過T9IME就可以大大提高輸入速度和簡潔度。
如何?T9IME呢?
(1)建立詞庫
將大量單詞儲備起來便於快速尋找,字典樹無疑是很好的選擇。每個節點將儲存此首碼的可能度,結構如下:
/* * 字典樹 */public class Trie {public Node root = new Node();//字典樹根節點public class Node{public int probablity;public Node[] next;public Node() {this.probablity = 0;next = new Node[26];}}public void insert(String str, int probablity){Node p = root;int i = 0;for(i = 0; i < str.length(); i++){if(p.next[str.charAt(i) - 'a'] != null){p = p.next[str.charAt(i) - 'a'];p.probablity += probablity;} else {Node q = new Node();q.probablity = probablity;p.next[str.charAt(i) - 'a'] = q;p = p.next[str.charAt(i) - 'a'];}}}public int search(String str){Node p = root;int i = 0;for(i = 0; i < str.length(); i++){if(p.next[str.charAt(i) - 'a'] != null){p = p.next[str.charAt(i) - 'a'];} else {return 0;}}return p.probablity;}}
(2)尋找
建立好的字典樹,每個節點最多有26個孩子分別代表下一個字元。當給出一個尋找串“43556”的時候,利用廣度優先遍曆來搜尋長度x的所有首碼的可能度。找出最大的即可。廣搜的時候要用到隊列。
舉例類比過程:
當輸入4(g,h,i)之後,通過字典樹遍曆發現只有"h","i",找出可能讀最大的輸出(i),並將h,i都入隊。
輸入3(d,e,f)後,拿出隊列中的"h",分別組成"hd","he","hf",去字典樹中查,將其中合法串入隊,記錄最大可能度對應串。再將h出隊。對"i"做同樣操作。最終找出最大的可能讀最大串。
……
可以看出廣搜的過程中大量剪枝,以及常用單詞的長度最多不過十幾個字母。所以字典樹的深度也是十幾,加上大量剪枝,效能還不錯。
static int[][] ref = {//手機鍵盤數字-字母映射表{0},{0},{3, 0, 1, 2},//按鈕2,三個字母a,b,c{3, 3, 4, 5},{3, 6, 7, 8},{3, 9, 10, 11},{3, 12, 13, 14},{4, 15, 16, 17, 18},{3, 19, 20, 21},{4, 22, 23, 24, 25}};public static Queue<String> queue = new LinkedList<String>();//用於廣度優先遍曆過程中的隊列public static Trie trie;//字典樹public static void BFS(String str){queue.clear();queue.offer("");int i = 0;for(i = 0; '1' != str.charAt(i); i++){int max_probablity = 0; //最大可能性值String probaStr = "";int pre_amount = queue.size(); //隊列中之前串的個數int j = 0;for(j = 0; j < pre_amount; j++){int k = 0;String preStr = queue.peek();for(k = 1; k <= ref[str.charAt(i) - '0'][0]; k++){String tempStr = preStr.concat((char)(ref[str.charAt(i) - '0'][k] + 97) + "");if(trie.search(tempStr) > 0){queue.offer(tempStr);}if(trie.search(tempStr) > max_probablity){max_probablity = trie.search(tempStr);probaStr = tempStr; }}queue.poll();}if("".equals(probaStr)){break;} else {System.out.println(probaStr);}}while('1' != str.charAt(i++)){System.out.println("MANUALLY");}}
思考:
1.以上類比過程只是給出最大可能度的串,也可以按可能度將所有匹配串按順序都給出,然後由使用者選擇。
2.感覺T9IME打破了之前IME的僵局,雖然只是用在手機輸入。但是個人認為當前流行的智能鍵盤IME也採用了類似的處理。比如利用搜狗IME依次輸入"hao""zi""wei""zhi"
給出的最大候選依次為:“好”“耗子”“好滋味”“好自為之”。是不是有點T9IME的味道?如果有興趣的話可以交流討論!