- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在寻找一种有效的数据结构/算法来存储和搜索基于音译的单词查找(就像谷歌做的那样:http://www.google.com/transliterate/ 但我没有尝试使用谷歌音译 API)。不幸的是,我尝试使用的自然语言没有实现任何 soundex,所以我只能靠自己了。
对于一个开源项目,我目前使用纯数组来存储单词列表并动态生成正则表达式(基于用户输入)来匹配它们。它工作正常,但正则表达式太强大或占用资源太多,超出了我的需要。例如,如果我尝试将此解决方案移植到手持设备上,我担心它会耗尽太多电池电量,因为使用正则表达式搜索数千个单词的成本太高。
对于复杂的语言,必须有更好的方法来完成这个,例如拼音输入法是如何工作的?关于从哪里开始的任何建议?
提前致谢。
编辑:如果我理解正确,这是@Dialecticus 的建议-
我想从Language1,它有3个字符a,b,c
音译到Language2,它有6个字符 p,q,r,x,y,z
。由于每种语言所拥有的字符数量及其音素的差异,通常无法定义一对一的映射。
让我们从语音上假设这是我们的关联数组/音译表:
a -> p, q
b -> r
c -> x, y, z
对于 Language2,我们也有一个有效的单词列表,以普通数组形式显示:
...
px
qy
...
如果用户键入ac
,在音译步骤1之后可能的组合变成px, py, pz, qx, qy, qz
。在步骤2中我们必须做在有效单词列表中进行另一次搜索,并且必须消除除 px
和 qy
之外的所有单词。
我目前所做的与上述方法没有什么不同。我没有使用音译表进行可能的组合,而是构建了一个正则表达式 [pq][xyz]
并将其与我的有效单词列表匹配,它提供了输出 px
和 qy
。
我很想知道是否有比这更好的方法。
最佳答案
据我了解,您有一个字母表中的输入字符串 S(我们称之为 A1),您希望将其转换为字符串 S',它在另一个字母表 A2 中是等效的。实际上,如果我理解正确的话,您想生成一个可能等同于 S 的输出字符串列表 [S'1,S'2,...,S'n]。
想到的一种方法是为 A2 中有效单词列表中的每个单词生成 A1 中匹配的字符串列表。使用您编辑中的示例,我们有
px->ac
qy->ac
pr->ab
(为了清楚起见,我添加了一个额外的有效词 pr
)
现在我们知道了哪些可能的输入符号系列总是映射到一个有效的单词,我们可以使用我们的表来构建一个 Trie .
每个节点都将持有一个指向 A2 中有效单词列表的指针,这些单词映射到 A1 中的符号序列,这些符号序列构成了从 Trie 的根到当前节点的路径。
因此对于我们的示例,Trie 看起来像这样
Root (empty)
| a
|
V
+---Node (empty)---+
| b | c
| |
V V
Node (px,qy) Node (pr)
从根节点开始,随着符号被消耗,从当前节点到其标有被消耗符号的子节点进行转换,直到我们读取整个字符串。如果在任何时候都没有为该符号定义转换,则输入的字符串在我们的 trie 中不存在,因此不会映射到目标语言中的有效单词。否则,在过程结束时,与当前节点关联的单词列表是输入字符串映射到的有效单词列表。
除了构建 trie 的初始成本(如果我们不想更改有效单词列表,可以预先构建 trie),这需要 O(n) 的输入长度来查找列表映射有效词。
使用 Trie 还提供了一个优势,您还可以使用它来查找所有有效单词的列表,这些单词可以通过在输入的末尾添加更多符号来生成 - 即前缀匹配。例如,如果输入符号“a”,我们可以使用 trie 查找所有以“a”开头的有效单词(“px”、“qr”、“py”)。但是这样做不如找到完全匹配的速度快。
下面是解决方案的快速破解(使用 Java):
import java.util.*;
class TrieNode{
// child nodes - size of array depends on your alphabet size,
// her we are only using the lowercase English characters 'a'-'z'
TrieNode[] next=new TrieNode[26];
List<String> words;
public TrieNode(){
words=new ArrayList<String>();
}
}
class Trie{
private TrieNode root=null;
public void addWord(String sourceLanguage, String targetLanguage){
root=add(root,sourceLanguage.toCharArray(),0,targetLanguage);
}
private static int convertToIndex(char c){ // you need to change this for your alphabet
return (c-'a');
}
private TrieNode add(TrieNode cur, char[] s, int pos, String targ){
if (cur==null){
cur=new TrieNode();
}
if (s.length==pos){
cur.words.add(targ);
}
else{
cur.next[convertToIndex(s[pos])]=add(cur.next[convertToIndex(s[pos])],s,pos+1,targ);
}
return cur;
}
public List<String> findMatches(String text){
return find(root,text.toCharArray(),0);
}
private List<String> find(TrieNode cur, char[] s, int pos){
if (cur==null) return new ArrayList<String>();
else if (pos==s.length){
return cur.words;
}
else{
return find(cur.next[convertToIndex(s[pos])],s,pos+1);
}
}
}
class MyMiniTransliiterator{
public static void main(String args[]){
Trie t=new Trie();
t.addWord("ac","px");
t.addWord("ac","qy");
t.addWord("ab","pr");
System.out.println(t.findMatches("ac")); // prints [px,qy]
System.out.println(t.findMatches("ab")); // prints [pr]
System.out.println(t.findMatches("ba")); // prints empty list since this does not match anything
}
}
这是一个非常简单的 trie,没有压缩或加速,并且只适用于输入语言的小写英文字符。但它可以很容易地修改为其他字符集。
关于algorithm - 用于基于音译的单词查找的高效数据结构/算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7537662/
有没有办法让音译在 Emacs 中工作,就像现在在 Gmail 中一样?我特别有兴趣让它在西里尔文中工作。 作为引用,Gmail 执行以下操作:我可以输入svoboda,它会输出свобода。这允许
ruby中非英文字符的音译最简单的方法是什么。即转换如: 翻译“Gévry” #=> "Gevry" 最佳答案 Ruby 有一个 Iconv其 stdlib 中的库以与通常的 iconv 命令非常相似
ruby 1.9.3 警告 iconv 弃用,但我使用 iconv 删除变音符号以从 Iconv.iconv('asccii//translit', 'utf-8', 'Těžiště') 返回 Te
在 Ruby on Rails 中,您可以轻松地将“任何”文本转换为适用于子域/路径名的格式。 1) "I am nobody." -> "i-am-nobody" 2) "Grünkohl is a
我想将西里尔文字符串音译成最接近的拉丁文等价物。例如。 “матрешка”=> “matreshka”,“водка”=> “伏特加”。所以理想情况下,我希望在 NSString 或其他已经了解字母
以下是将 Google Transliteration 代码集成到 ASP.Net Pages 中的示例代码(随处可用)。 但我的问题是,如何在将在运行时生成的文本框中启用音译?此脚本需要文本框的 I
我正在使用 Java Swing 开发一个音译项目。它可以访问互联网,但我无法设置它。我们该怎么做?我们需要下载 Google API 库还是只需要一个函数调用就可以了? 这里有一些有用的音译链接:
在我们的 RoR 项目中,我们使用 postgres unaccent 函数来检索我们模型名称属性之一的非重音版本。 name 属性可以包含来自各种语言的任何重音字符。然后我们将其保存为 unacce
如何在我的 Java 应用程序中使用 Google Transliteration API。 如果我给一个String(英语或阿拉伯语)作为输入,Google Transliterator API 应
我正在做一个基于泰米尔语的 Web 应用程序。在我的应用程序中,我使用动态字段来添加用户详细信息。那么,动态字段有多个 ID 如何做到这一点或如何使用基于类的 Google 音译? // Lo
我有一个字符串对象 “有多个字符甚至特殊字符” 我正在尝试使用 UTF8Encoding utf8 = new UTF8Encoding(); ASCIIEncoding ascii = new AS
我使用过“Google AJAX Transliteration API”,它对我来说很顺利。 http://code.google.com/apis/ajaxlanguage/documentati
我是一名优秀的程序员,十分优秀!