大家好,欢迎来到IT知识分享网。
由于现在使用拼音输入法较多,很可能输入同音字而无法搜索到结果,或者由于普通话不标准(前后鼻音不分)输入了错误的拼音。例如用户想搜索”牛奶“却输入了刘来(liulai),那我们可以对liulai进行模糊音扩展,然后一起放到搜索引擎中去搜索。为了避免过度扩展曲解了用户的意图,对于扩展词需要进行排序,越少改动越排在前面(原文排在最前),越多改动越排在后面。在搜索时按照顺序赋予不同的权重。
类似这样:
"query": {"bool":{ "should":[ {"match" : { "t.py":{"query": "lanqiuxie","analyzer":"whitespace","operator":"or" ,"boost":3}}}, {"match" : { "t.py":{"query": "langqiuxie","analyzer":"whitespace","operator":"or" ,"boost":3}}}, {"match" : { "t.py":{"query": "nangqiuxie","analyzer":"whitespace","operator":"or" ,"boost":2}}}, {"match" : { "t.py":{"query": "nanqiuxie","analyzer":"whitespace","operator":"or" ,"boost":1}}}]}}}
好,现在show一下模糊拼音扩展的算法:
1.声母l和n互换
2.韵母有g和没g互换。
3.变换少的排在前面。
例如 [“liulai”] => [“liulai”,”liunai”,”niulai”,”niunai”]
//汉语拼音模糊音扩展 static public List<String> expand(String[] ss) { int n = ss.length; List<String>[] lists = new ArrayList[n]; List<Integer> changes = new ArrayList<>(); for (int i = 0; i < n; i++) { lists[i] = expandOne(ss[i]); if (lists[i].size() > 1) changes.add(i); } int max = changes.size(); if (max > 4) max = 4; List<String> ans = new ArrayList<>(); for (int i = 0; i <= max; i++) { ans.addAll(miss(lists, changes, i, 0, 0)); } return ans; } static private Map<String, String> confusingMap = new HashMap<String, String>() {
{ this.put("in", "ing"); this.put("an", "ang"); this.put("en", "eng"); this.put("un", "ong"); }}; static private List<String> miss(List<String>[] lists, List<Integer> changes, int c, int b1, int b2) { List<String> list = new ArrayList<>(); if (c > changes.size() - b2 || c < 0) return list; int n = lists.length; if (c == 0) { StringBuilder sb = new StringBuilder(); for (int i = b1; i < n; i++) { sb.append(lists[i].get(0)); } list.add(sb.toString()); } else { int fc = changes.get(b2); StringBuilder sb = new StringBuilder(); for (int i = b1; i < fc; i++) { sb.append(lists[i].get(0)); } String pre = sb.toString(); List<String> left = miss(lists, changes, c - 1, fc + 1, b2 + 1); for (int i = 1; i < lists[fc].size(); i++) { for (String s : left) { list.add(pre + lists[fc].get(i) + s); } } pre += lists[fc].get(0); left = miss(lists, changes, c, fc + 1, b2 + 1); for (String s : left) { list.add(pre + s); } } return list; } static private List<String> expandOne(String py) { List<String> list = new ArrayList<>(); list.add(py); if (py.equals("yang") || py.equals("yan")) return list; if (py.startsWith("l") || py.startsWith("n")) { List<String> vs = changeVowel(py.substring(1)); String[] ln = py.startsWith("l") ? new String[]{"l", "n"} : new String[]{"n", "l"}; for (String sm : ln) { for (String s : vs) { String nw = sm + s; if (!nw.equals(py)) list.add(nw); } } } else { List<String> vs = changeVowel(py); return vs; } return list; } static private List<String> changeVowel(String s) { List<String> list = new ArrayList<>(); list.add(s); if (s.endsWith("iang") || s.endsWith("ian")) return list; int len = s.length(); for (Map.Entry<String, String> en : confusingMap.entrySet()) { String k = en.getKey(), v = en.getValue(); if (s.endsWith(k)) { list.add(s.substring(0, len - k.length()) + v); break; } else if (s.endsWith(v)) { list.add(s.substring(0, len - v.length()) + k); break; } } return list; } public static void main(String[] args) { System.out.println(expand(new String[]{"niu","nai"})); }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/158940.html