前言:

最近在做一个调研的工作。研究的对象是搜索引擎中关键词的纠错功能。就像百度中搜索某一个关键词“ABC”,它会在搜索的结果中对此关键词进行纠正,然后会显示:你要找的是不是“ABD”。这种之类的。这个是背景,不过本文中还没不是介绍这一功能,这一功能的说明会在我的调研结束之后写在我的博客中。

本文要介绍的是,对拼音的拼写进行智能切分。比如:qinshimingyuezhijunlintianxia这一串拼音字符串,我们要如何对其进行切分呢?本文将要用两种方法介绍这个汉语拼音的智能切分功能。

商业转载请联系作者获得授权,非商业转载请注明出处。
本文作者:Q-WHai
发表日期: 2015年10月13日
本文链接:http://blog.csdn.net/lemon_tree12138/article/details/49074809
来源:CSDN
更多内容:分类 >> 算法与数学

1.字典树算法

关于字典树(Trie tree),大家可以从下面的展示图中看出。

(1)基本算法的实现

这里我想先就这个算法做一个基本的实现,再在这个基础上做拼音的智能切分。毕竟路是一步一步走出来的,不必要急于求成,这也是在软件开发过程中一个很关键的地方。

我们使用面向对象的编程语言Java来编写代码。在图中可以看出,每个节点即是一个对象。这个对象有以下一些属性:节点名称信息/词频/是否是单词的结尾字母/是否是root节点/孩子节点。而对于整个一棵树又是另外的一个对象。于是,我们可以编写出如下的代码:

节点对象:

public class Node {String name; // 结点的字符名称int fre; // 单词的词频boolean end; // 是否是单词结尾boolean root; // 是否是根结点Map<String, Node> childrens; // 子节点信息public Node(String name) {this.name = name;if (childrens == null) {childrens = new HashMap<String, Node>();}setFre(0);setRoot(false);setEnd(false);}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getFre() {return fre;}public void setFre(int fre) {this.fre = fre;}public boolean isEnd() {return end;}public void setEnd(boolean end) {this.end = end;}public boolean isRoot() {return root;}public void setRoot(boolean root) {this.root = root;}public Map<String, Node> getChildrens() {return childrens;}public void setChildrens(Map<String, Node> childrens) {this.childrens = childrens;}
}

字典树对象:

public class TrieTree {Node root;public TrieTree(String name) {root = new Node(name);root.setFre(0);root.setEnd(false);root.setRoot(true);}public void insert(String word) {...}public int searchFre(String word) {...}
}

测试代码:

public class TireTest {public static void main(String[] args) {TrieTree tree = new TrieTree("test");tree.insert("word");tree.insert("word");tree.insert("hello");tree.insert("hi");System.out.println("word " + tree.searchFre("word"));System.out.println("hello " + tree.searchFre("hello"));System.out.println("hi " + tree.searchFre("hi"));System.out.println("hell " + tree.searchFre("hell"));System.out.println("hellt " + tree.searchFre("hellt")); // qinshimingyuezhijunlintianxia}
}

测试结果:

word 2
hello 1
hi 1
hell 0
hellt -1

在上面的字典树对象的代码中,我把两个最关键方法给略去了,这里我给补上,目的只是强调这两个方法的关键性,别无他意。

插入:

对于插入单词操作。因为单词的长度是已知的,所以,这里我们就可以以单词长度作为限制进行循环。在插入单词的过程中,如果某一个字母已经存在,则将遍历的位置移至此节点,如果发现某一个字母不存在,则新建一个,再移动遍历节点。

public void insert(String word) {Node node = root;char[] words = word.toCharArray();for (int i = 0; i < words.length; i++) {if (node.getChildrens().containsKey(words[i] + "")) {if (i == words.length - 1) {Node endNode = node.getChildrens().get(words[i] + "");endNode.setFre(endNode.getFre() + 1);endNode.setEnd(true);}} else {Node newNode = new Node(words[i] + "");if (i == words.length - 1) {newNode.setFre(1);newNode.setEnd(true);newNode.setRoot(false);}node.getChildrens().put(words[i] + "", newNode);}node = node.getChildrens().get(words[i] + "");}}

查找:

对于查找,相对于插入代码量要小一些。这是因为在查找的过程中,如果找到了就继续直到单词结尾,如果没找到就返回,很干脆。

public int searchFre(String word) {int fre = -1;Node node = root;char[] words = word.toCharArray();for (int i = 0; i < words.length; i++) {if (node.getChildrens().containsKey(words[i] + "")) {node = node.getChildrens().get(words[i] + "");fre = node.getFre();} else {fre = -1;break;}}return fre;}

(2)拼音智能切分

对于拼音智能切分,我们就利用了上面的字典。如果你认真看了上面的说明和代码实践或是你已经了解了字典树,那么我想关于这里的拼音切分就更加难不倒你了。因为在上面代码的基础上,我们只做一点点的修改,就可以完成我们理想拼音智能切分了。如下:

public String splitSpell(String spell) {Node node = root;char[] letters = spell.toCharArray();String spells = "";for (int i = 0; i < letters.length; i++) {if (node.getChildrens().containsKey(letters[i] + "")) {spells += letters[i];node = node.getChildrens().get(letters[i] + "");} else {node = root;spells += " ";i--;}}return spells;}

结果:

对拼音串qinshimingyuezhijunlintianxia的切分结果如下:

qin shi ming yue zhi jun lin tian xia

2.正则匹配

关于正则的匹配,这里就不作过多的说明。代码如下:

public static String splitSpell(String s) {String regEx = "[^aoeiuv]?h?[iuv]?(ai|ei|ao|ou|er|ang?|eng?|ong|a|o|e|i|u|ng|n)?";int tag = 0;String spell = "";List<String> tokenResult = new LinkedList<String>();for (int i = s.length(); i > 0; i = i - tag) {Pattern pat = Pattern.compile(regEx);Matcher matcher = pat.matcher(s);matcher.find();spell += (matcher.group() + " ");tag = matcher.end() - matcher.start();tokenResult.add(s.substring(0, 1));s = s.substring(tag);}return spell;}

源码下载:

代码为完整源码,包含完整的代码实现和完整的拼音表

http://download.csdn.net/detail/u013761665/9175663

算法:两种对拼音进行智能切分的方法相关推荐

  1. 计算机提取干涉条纹原理,两种提取Fabry-Perot干涉条纹圆心的新方法

    摘要本文介绍两种提取Fabry-Perot干涉条纹圆心点坐标的新方法.首先对干涉图像依次进行二值化处理,对所得到的条纹强度曲线进行均平滤波和自适应滤波,根据条纹灰度值强度余弦函数分布的特点,对条纹灰度 ...

  2. 怎么给照片降噪?分享两种简单好用的图片降噪方法

    怎么给照片降噪呢?大家在使用数码摄影的时候,相机将光线作为接收信号接收并输出的过程中,会产生图片中粗糙的部分,这本是不该出现的外来像素,导致拍出来的照片或多或少会出现噪点,让图片看起来不美观.这时候我 ...

  3. 两种解决Qt5显示中文乱码的方法(使用QStringLiteral和#pragma execution_character_set(utf-8)两种方法)

    两种解决Qt5显示中文乱码的方法(使用QStringLiteral和#pragma execution_character_set("utf-8")两种方法) 升级到Qt5.X之后 ...

  4. 如何给html文件夹密码,怎样给文件夹加上密码_分享两种给文件夹设密码的方法...

    现在大家习惯把重要的文件或比较隐私的文件存放在电脑上,出于安全考虑,大家会选择给文件夹设密码.但是问题来了,怎样给文件夹加密码呢?估计大多数的人都还不太清楚该怎么设置吧,别着急,这里小编分享两种给文件 ...

  5. 下载的音乐如何转成MP3?分享两种将音频转换为MP3格式的方法

    如果您下载了一些音频文件,但是它们不是MP3格式,那么您可能需要将它们转换为MP3格式,以便在各种设备上播放.以下是两种将音频转换为MP3格式的方法. 方法一:使用免费的在线转换工具 有许多免费的在线 ...

  6. 两种查看表空间使用情况的方法

    本文简单介绍两种查看表空间使用情况的方法. 方法一. SELECT c.tablespace_name "表空间", ROUND(a.bytes/1048576,2) " ...

  7. [算法]两种水果杂交出一种新水果,现在给新水果取名,要求这个名字中包含了以前两种水果名字的字母,并且这个名字要尽量短。

    问题: 两种水果杂交出一种新水果,现在给新水果取名,要求这个名字中包含了以前两种水果名字的字母,并且这个名字要尽量短.也就是说以前的一种水果名字arr1是新水果名字arr的子序列,另一种水果名字arr ...

  8. C语言回音消除算法,一种语音识别场景中回音消除的方法

    主权项: 1.一种语音识别场景中回音消除的方法,其特征在于:该方法在硬件方面的预置条件为:音频输入为两个数字麦克,在物理电路上,连接数字麦克1,不连接数字麦克2,即数字麦克2虚焊,不连接真实的数字麦克 ...

  9. 区别于传统低效标注,两种基于自然语言解释的数据增强方法

    本文内容整理自 PaperWeekly 和 biendata 在 B 站组织的直播回顾,点击文末阅读原文即可跳转至 B 站收看本次分享完整视频录像,如需嘉宾课件,请在 PaperWeekly 公众号回 ...

  10. 两种常见挂载Jenkins slave节点的方法

    1.挂载slave节点的方法 在Jenkins的Master上,进入Mange node页面,可以管理node节点,例如新加.删除等操作. 其中, Name是节点名字: Description是节点描 ...

最新文章

  1. Fabric--CA 应用与配置
  2. jupyter 接受参数
  3. nginx核心模块常用指令
  4. day10-协程遇到IO操作自动切换
  5. MFC工作笔记0006---#pragma warning(disable:4996)是什么意思
  6. 【FFMPEG系列】windows下编译ffmpeg且加入libx264
  7. 行内元素多出的空白文本节点的解决方法
  8. Vijos 1303
  9. 用 Python 自动定时发微博
  10. html简繁体转换,在线繁体字转换工具
  11. vue-pdf的使用
  12. 如何下载喜马拉雅里面的音频文件
  13. 强化学习基础(第一周)笔记和代码(RL-cousera)
  14. AE 3D摄像机工作原理
  15. Ogre Giles
  16. C++编程 一个正整数的立方和
  17. Ubuntu安装samb服务
  18. 4.20微众银行暑期实习前端一面
  19. python 实现热门音乐分析 附代码+数据 +论文
  20. 响应式设计布局要不要了解一下?

热门文章

  1. 自动升级系统的设计与实现(源码)
  2. 全志A31S(android 4.2/4.4)截屏
  3. qq同步android 2.2,支持手机号注册!Android QQ同步助手2.1发布
  4. Windows 10不能安装mini版迅雷的解决方法
  5. MAD、AMV、MMD 的区别
  6. 不能说のsecret 5
  7. SNN系列|神经元模型篇(4) LIF
  8. lodop 调用打印机打印条码
  9. 视频录制软件进行电脑屏幕录像的使用方法
  10. 魔兽世界服务器维护掉线,《魔兽世界怀旧服》老是掉线怎么办 老是掉线解决办法...