草庐IT

c++ - 如何确定普通话字符的 Levenshtein 距离?

coder 2023-06-04 原文

我们正在开发一个系统,使用 UTF-8、UTF-16 和 UTF-32 Unicode 字符标准对 50 多种国际语言进行模糊匹配。到目前为止,我们已经能够使用 Levenshtein 距离来检测德语 Unicode 扩展字符单词的拼写错误。

我们想扩展这个系统来处理以 Unicode 表示的普通话中文表意文字。我们将如何进行相似汉字之间的 Levenshtein 距离计算?

最佳答案

首先,澄清一下:汉字并不等同于德语或英语 .大多数你认为是词的东西(使用“词”的语义或句法定义)由 1-3 个字符组成。通过将这些字符序列表示为 UCS-2 或 UCS-4 代码点序列,可以直接将 Levenshtein 距离应用于此类字符序列。由于大多数单词都很短(尤其是长度为 1 或 2 个字符的单词),但它的用途可能有限。

但是,由于您的问题专门针对 单个字符之间的编辑距离 ,我相信需要一种不同的方法,这可能确实非常困难。

首先,您必须将每个字符表示为它所包含的组件/笔画的序列。有两个问题:

  • 一些组件本身包含更小的 组件 ,因此如何将字符分解为“原子”组件并不是唯一定义的。如果你做到个人层面笔画 ,您需要对每个笔画进行表征(字符内的位置、形状、方向等)。我不认为每个人都这样做(如果有人告诉我,我会最感兴趣)。
  • 您需要将笔画或组件放入 订购 .明显的候选者是字符的规范笔顺,这是在 lexica 中描述的,甚至还有带有动画笔顺图的词典网站。但是,我知道的数据源(日语)将这些动画生成为位图图形序列;我从未见过以适合编辑距离计算的形式表示笔画序列(甚至单个笔画的名称)的人类或机器可读代码。

  • 不过,您可以尝试的最后一件事是渲染角色 字形 并根据需要更改多少像素(或 vector )以将一个字符转换为另一个字符来计算编辑距离。我曾经在 OCR 后更正的上下文中对拉丁字符和字符组合(以像素为基础)进行了此操作,结果非常令人鼓舞。

    对 larsmans 评论的快速回答如下:Unicode 标准定义了两个相关概念(在下面我指的是 6.0 version, chapter 12):
  • 基于部首和笔画计数的索引。每个汉字由几个部分组成,其中之一是部首。部首/笔画计数索引是按部首排序的字符列表(即,共享相同部首的所有字符组合在一起),并且每个部首特定组在内部按字符其余部分使用的笔画数排序。不幸的是,即使这也不是唯一定义的——有些字符的部首由不同的传统词汇定义,并且笔画计数也可能很困难。这是Unicode标准所说的:

    To expedite locating specific Han ideographic characters in the code charts, radical-stroke indices are provided on the Unicode web site. [...] The most influential authority for radical-stroke information is the eighteenth-century KangXi dictionary, which contains 214 radicals. The main problem in using KangXi radicals today is that many simplified characters are difficult to classify under any of the 214 KangXi radicals. As a result, various modern radical sets have been introduced. None, however, is in general use, and the 214 KangXi radicals remain the best known. [...] The Unicode radical-stroke charts are based on the KangXi radicals. The Unicode Standard follows a number of different sources for radical-stroke classification. Where two sources are at odds as to radical or stroke count for a given character, the character is shown in both positions in the radical-stroke charts.



    请注意,即使我们假设部首/笔画索引是明确且正确的,也不足以作为将字符转换为组件序列的信息源,因为由此完全描述的字符的唯一组件是激进的。
  • 表意描述序列(第 12.2 节):Unicode 为字符的基本组成部分定义了代码点(它们中的大多数本身无论如何都可以用作独立字符),并且有代码点用于将它们粘合在一起以形成描述字符的组成部分的序列组成一个更复杂的字符。因此,这与组合字符的工作方式类似,但存在重要区别:
  • 组件的顺序不是唯一定义的
  • 对于此类序列,没有定义渲染机制
  • 没有从普通字符到相应的表意描述序列的映射(尽管标准提到这种映射在某种程度上存在于它们用于编译汉字符集的源中)。

  • 该标准建议使用表意描述序列来描述没有由任何现有代码点表示的复杂或稀有字符;但它明确不鼓励使用描述序列代替普通字符:

    In particular, Ideographic Description Sequences should not be used to provide alternative graphic representations of encoded ideographs in data interchange. Searching, collation, and other content-based text operations would then fail.

    关于c++ - 如何确定普通话字符的 Levenshtein 距离?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12380619/

    有关c++ - 如何确定普通话字符的 Levenshtein 距离?的更多相关文章

    1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

      我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

    2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

      总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

    3. Ruby 解析字符串 - 2

      我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

    4. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

      我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

    5. ruby-on-rails - unicode 字符串的长度 - 2

      在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)

    6. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

      关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

    7. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

      给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

    8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    9. ruby - 将差异补丁应用于字符串/文件 - 2

      对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

    10. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

      大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

    随机推荐