iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >怎么在Java中实现一个双向匹配分词算法
  • 873
分享到

怎么在Java中实现一个双向匹配分词算法

java 2023-05-30 16:05:48 873人浏览 安东尼
摘要

本篇文章为大家展示了怎么在Java中实现一个双向匹配分词算法,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。正向最大匹配分词:该算法是基于分词词典实现,从字符串左侧进行分割匹配,如果词典存在则返回分割

本篇文章为大家展示了怎么在Java中实现一个双向匹配分词算法,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

正向最大匹配分词:

该算法是基于分词词典实现,从字符串左侧进行分割匹配,如果词典存在则返回分割出来的词语并将该词从之前的字符串中切除,循环进行切割直到字符串大小为0。

例如:str = "我们都是西北农林科技大学信息工程学院的学生。",(假设我们定义最大切割长度max = 8,也就是八个汉字)

定义分词长度len = max,从左边取出len个字符Word = "我们都是西北农林",并在字典中匹配word;
2.字典中没有该词,那么去掉最后一个字符赋值给word,len值减1;
3.重复步骤2,直到在字典中找到该词或是len = 1,退出循环;
4.从str中切除掉已分割的词语,重复进行1、2、3步骤,直到str被分解完。

逆向最大匹配分词:

和正向分词算法一样,只是从字符串的右边开始切分词语,直到字符串长度为0,。这里不再赘述。

双向匹配分词:

该方法是在正向分词和逆向分词的基础上,对于分割有歧义的语句进行歧义分词。提出“贪吃蛇算法”实现。要进行分词的字符串,就是食物。有2个贪吃蛇,一个从左向右吃;另一个从右向左吃。只要左右分词结果有歧义,2条蛇就咬下一口。贪吃蛇吃下去的字符串,就变成分词。 如果左右分词一直有歧义,两条蛇就一直吃。两条蛇吃到字符串中间交汇时,就肯定不会有歧义了。这时候,左边贪吃蛇肚子里的分词,中间没有歧义的分词,右边贪吃蛇肚子里的分词,3个一拼,就是最终的分词结果。

本文是对整段话进行分词,首先将这段话根据标点符号断句,然后将每句话再进行分词输出。

package cn.nwsuaf.spilt;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Scanner;public class WordSpilt {    private Map<String, Integer> map = new HashMap<String, Integer>();    private int MAX_LENGTH = 5;    public WordSpilt() throws IOException {    BufferedReader br = new BufferedReader(new FileReader("src/dict.txt"));    String line = null;    while ((line = br.readLine()) != null) {      line = line.trim();      map.put(line, 0);    }    br.close();  }    public void setMaxLength(int max) {    this.MAX_LENGTH = max;  }    public int getMaxLength() {    return this.MAX_LENGTH;  }    public List<String> spilt(String spiltStr, boolean leftToRight) {    // 如果带切分字符串为空则返回空    if (spiltStr.isEmpty())      return null;    // 储存正向匹配分割字符串    List<String> leftWords = new ArrayList<String>();    // 储存负向匹配分割字符串    List<String> rightWords = new ArrayList<String>();    // 用于取切分的字串    String word = null;    // 取词的长度,初始化设置为最大值    int wordLength = MAX_LENGTH;    // 分词操作中处于字串当前位置    int position = 0;    // 已经处理字符串的长度    int length = 0;    // 去掉字符串中多余的空格    spiltStr = spiltStr.trim().replaceAll("\\s+", "");    // 当待切分字符串没有被切分完时循环切分    while (length < spiltStr.length()) {      // 如果还没切分的字符串长度小于最大值,让取词词长等于该词本身长度      if (spiltStr.length() - length < MAX_LENGTH)        wordLength = spiltStr.length() - length;      // 否则取默认值      else        wordLength = MAX_LENGTH;      // 如果是正向最大匹配,从spiltStr的position处开始切割      if (leftToRight) {        position = length;        word = spiltStr.substring(position, position + wordLength);      }      // 如果是逆向最大匹配,从spiltStr末尾开始切割      else {        position = spiltStr.length() - length;        word = spiltStr.substring(position - wordLength, position);      }      // 从当前位置开始切割指定长度的字符串      // word = spiltStr.substring(position, position + wordLength);      // 如果分词词典里面没有切割出来的字符串,舍去一个字符      while (!map.containsKey(word)) {        // 如果是单字,退出循环        if (word.length() == 1) {          // 如果是字母或是数字要将连续的字母或者数字分在一起          if (word.matches("[a-zA-z0-9]")) {            // 如果是正向匹配直接循环将后续连续字符加起来            if (leftToRight) {              for (int i = spiltStr.indexOf(word, position) + 1; i < spiltStr                  .length(); i++) {                if ((spiltStr.charAt(i) >= '0' && spiltStr                    .charAt(i) <= '9')                    || (spiltStr.charAt(i) >= 'A' && spiltStr                        .charAt(i) <= 'Z')                    || (spiltStr.charAt(i) >= 'a' && spiltStr                        .charAt(i) <= 'z')) {                  word += spiltStr.charAt(i);                } else                  break;              }            } else {              // 如果是逆向匹配,从当前位置之前的连续数字、字母字符加起来并翻转              for (int i = spiltStr.indexOf(word, position - 1) - 1; i >= 0; i--) {                if ((spiltStr.charAt(i) >= '0' && spiltStr                    .charAt(i) <= '9')                    || (spiltStr.charAt(i) >= 'A' && spiltStr                        .charAt(i) <= 'Z')                    || (spiltStr.charAt(i) >= 'a' && spiltStr                        .charAt(i) <= 'z')) {                  word += spiltStr.charAt(i);                  if (i == 0) {                    StringBuffer sb = new StringBuffer(word);                    word = sb.reverse().toString();                  }                } else {                  // 翻转操作                  StringBuffer sb = new StringBuffer(word);                  word = sb.reverse().toString();                  break;                }              }            }          }          break;        }        // 如果是正向最大匹配,舍去最后一个字符        if (leftToRight)          word = word.substring(0, word.length() - 1);        // 否则舍去第一个字符        else          word = word.substring(1);      }      // 将切分出来的字符串存到指定的表中      if (leftToRight)        leftWords.add(word);      else        rightWords.add(word);      // 已处理字符串增加      length += word.length();    }    // 如果是逆向最大匹配,要把表中的字符串调整为正向    if (!leftToRight) {      for (int i = rightWords.size() - 1; i >= 0; i--) {        leftWords.add(rightWords.get(i));      }    }    // 返回切分结果    return leftWords;  }    public boolean isEqual(List<String> list1, List<String> list2) {    if (list1.isEmpty() && list2.isEmpty())      return false;    if (list1.size() != list2.size())      return false;    for (int i = 0; i < list1.size(); i++) {      if (!list1.get(i).equals(list2.get(i)))        return false;    }    return true;  }    public List<String> resultWord(String inputStr) {    // 分词结果    List<String> result = new ArrayList<String>();    // “左贪吃蛇”分词结果    List<String> resultLeft = new ArrayList<String>();    // “中贪吃蛇”(分歧部分)分词结果    List<String> resultMiddle = new ArrayList<String>();    // “右贪吃蛇”分词结果    List<String> resultRight = new ArrayList<String>();    // 正向最大匹配分词结果    List<String> left = new ArrayList<String>();    // 逆向最大匹配分词结果    List<String> right = new ArrayList<String>();    left = spilt(inputStr, true);        right = spilt(inputStr, false);        // 判断两头的分词拼接,是否已经在输入字符串的中间交汇,只要没有交汇,就不停循环    while (left.get(0).length() + right.get(right.size() - 1).length() < inputStr        .length()) {      // 如果正逆向分词结果相等,那么取正向结果跳出循环      if (isEqual(left, right)) {        resultMiddle = left;        break;      }      // 如果正反向分词结果不同,则取分词数量较少的那个,不用再循环      if (left.size() != right.size()) {        resultMiddle = left.size() < right.size() ? left : right;        break;      }      // 如果以上条件都不符合,那么实行“贪吃蛇”算法      // 让“左贪吃蛇”吃下正向分词结果的第一个词      resultLeft.add(left.get(0));      // 让“右贪吃蛇”吃下逆向分词结果的最后一个词      resultRight.add(right.get(right.size() - 1));      // 去掉被“贪吃蛇”吃掉的词语      inputStr = inputStr.substring(left.get(0).length());      inputStr = inputStr.substring(0,          inputStr.length() - right.get(right.size() - 1).length());      // 清理之前正逆向分词结果,防止造成干扰      left.clear();      right.clear();      // 对没被吃掉的字符串重新开始分词      left = spilt(inputStr, true);      right = spilt(inputStr, false);    }    // 循环结束,说明要么分词没有歧义了,要么"贪吃蛇"从两头吃到中间交汇了    // 如果是在中间交汇,交汇时的分词结果,还要进行以下判断:    // 如果中间交汇有重叠了:    // 正向第一个分词的长度 + 反向最后一个分词的长度 > 输入字符串总长度,就直接取正向的    if (left.get(0).length() + right.get(right.size() - 1).length() > inputStr        .length())      resultMiddle = left;    // 如果中间交汇,刚好吃完,没有重叠:    // 正向第一个分词 + 反向最后一个分词的长度 = 输入字符串总长度,那么正反向一拼即可    if (left.get(0).length() + right.get(right.size() - 1).length() == inputStr        .length()) {      resultMiddle.add(left.get(0));      resultMiddle.add(right.get(right.size() - 1));    }    // 将没有歧义的分词结果添加到最终结果result中    for (String string : resultLeft) {      result.add(string);    }    for (String string : resultMiddle) {      result.add(string);    }    // “右贪吃蛇”存储的分词要调整为正向    for (int i = resultRight.size() - 1; i >= 0; i--) {      result.add(resultRight.get(i));    }    return result;  }    public List<String> resultSpilt(String inputStr) {    // 用于存储最终分词结果    List<String> result = new ArrayList<String>();    // 如果遇到标点就分割成若干句话    String regex = "[,。;!?]";    String[] st = inputStr.split(regex);    // 将每一句话的分词结果添加到最终分词结果中    for (String stri : st) {      List<String> list = resultWord(stri);      result.addAll(list);    }    return result;  }  public static void main(String[] args) {    // example:过来看房价贵不贵?乒乓球拍卖完了    Scanner input = new Scanner(System.in);    String str = input.nextLine();    WordSpilt wordSpilt = null;    try {      wordSpilt = new WordSpilt();    } catch (IOException e) {      e.printStackTrace();    }    List<String> list = wordSpilt.resultWord(str);    for (String string : list) {      System.out.print(string + "/");    }  }}

上述内容就是怎么在Java中实现一个双向匹配分词算法,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网精选频道。

--结束END--

本文标题: 怎么在Java中实现一个双向匹配分词算法

本文链接: https://www.lsjlt.com/news/219981.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么在Java中实现一个双向匹配分词算法
    本篇文章为大家展示了怎么在Java中实现一个双向匹配分词算法,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。正向最大匹配分词:该算法是基于分词词典实现,从字符串左侧进行分割匹配,如果词典存在则返回分割...
    99+
    2023-05-30
    java
  • 最大匹配分词算法怎么在Java项目中实现
    最大匹配分词算法怎么在Java项目中实现?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。全文检索有两个重要的过程:1分词2倒排索引我们先看分词算法目前对中文分词有两个方向,其...
    99+
    2023-05-31
    java 最大匹配分词算法 ava
  • 怎么在java中实现一个gc算法
    这期内容当中小编将会给大家带来有关怎么在java中实现一个gc算法,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. ...
    99+
    2023-06-14
  • Java中怎么实现一个TFIDF算法
    这篇文章给大家介绍Java中怎么实现一个TFIDF算法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。算法介绍最近要做领域概念的提取,TFIDF作为一个很经典的算法可以作为其中的一步处理。计算公式比较简单,如下:预处理由...
    99+
    2023-06-02
  • 怎么利用java实现一个二分法算法
    这篇文章给大家介绍怎么利用java实现一个二分法算法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。java 二分法算法1、前提:二分查找的前提是需要查找的数组必须是已排序的,我们这里的实现默认为升序2、原理:将数组分为...
    99+
    2023-05-31
    java 二分法算法 ava
  • 在Java中怎么实现一个快速排序算法
    在Java中怎么实现一个快速排序算法?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。快速排序的原理:选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序...
    99+
    2023-05-30
    java
  • 怎么在java项目中实现一个海盗算法
    今天就跟大家聊聊有关怎么在java项目中实现一个海盗算法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。具体方法如下:package unit4;public cl...
    99+
    2023-05-31
    java 海盗算法 ava
  • 怎么在Android开发中实现一个正则匹配功能
    这篇文章给大家介绍怎么在Android开发中实现一个正则匹配功能,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。在Android开发中,可能也会遇到一下输入框的合法性验证,这时候最常用的就应该是正则表达式去做一些匹配了,...
    99+
    2023-05-31
    android roi
  • java中怎么实现一个泛型算法
    java中怎么实现一个泛型算法,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。说明有界类型参数是实现泛型算法的关键。这个方法实现简单但无法编译,因为大于号的操作符(>)...
    99+
    2023-06-20
  • 怎么在react中实现一个diff算法
    这期内容当中小编将会给大家带来有关怎么在react中实现一个diff算法,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。单节点Diff单节点Diff比较简单,只有key相同并且type相同的情况才会尝试复用...
    99+
    2023-06-14
  • 怎么在Java项目中实现一个堆排序算法
    怎么在Java项目中实现一个堆排序算法?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。堆是数据结构中的一种重要结构,了解“堆”的概念和操作,可以帮助我们快速地掌握堆排序。堆的...
    99+
    2023-05-31
    java 堆排序算法 ava
  • 怎么在Java中利用TreeMap实现一个排序算法
    怎么在Java中利用TreeMap实现一个排序算法?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。TreeMap 和 HashMap 用法大致相同,但实际需求中,我们需要把一...
    99+
    2023-05-31
    java treemap 排序算法
  • 怎么在Android中利用DrawerLayout实现一个双向侧滑菜单
    这篇文章将为大家详细讲解有关怎么在Android中利用DrawerLayout实现一个双向侧滑菜单,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。布局文件的代码:<LinearLayou...
    99+
    2023-05-30
  • Vuejs中怎么实现一个搜索匹配功能
    这期内容当中小编将会给大家带来有关Vuejs中怎么实现一个搜索匹配功能,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。<!DOCTYPE html> ...
    99+
    2024-04-02
  • 怎么在Java项目中实现一个求逆矩阵算法
    这篇文章给大家介绍怎么在Java项目中实现一个求逆矩阵算法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。实现方法如下:package demo;public class MatrixInverse { public ...
    99+
    2023-05-31
    java 求逆矩阵算法 ava
  • 怎么在java中利用GUI实现一个加法计算器
    怎么在java中利用GUI实现一个加法计算器?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。java基本数据类型有哪些Java的基本数据类型分为:1、整数类型,用来表示整数的数据...
    99+
    2023-06-14
  • Java中怎么实现一个双数组Trie树
    本篇文章给大家分享的是有关Java中怎么实现一个双数组Trie树,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。对于插入字符串,如果有一个字符串是另一个字符串的子串的话,我是将结...
    99+
    2023-06-17
  • java中的双向链表怎么实现
    在Java中,可以使用自定义的双向链表类来实现双向链表。以下是一个简单的双向链表的实现示例: public class Doubly...
    99+
    2023-10-24
    java
  • Java中怎么实现一个通用组合算法
    Java中怎么实现一个通用组合算法,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Java实现通用组合算法,存在一个类似{31311133,33113330}这样的集合,经过...
    99+
    2023-06-17
  • 怎么在java项目中实现一个二叉查找树算法
    今天就跟大家聊聊有关怎么在java项目中实现一个二叉查找树算法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。具体内容如下package 查找;import edu...
    99+
    2023-05-31
    java 二叉查找树 ava
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作