精华内容
下载资源
问答
  • Java 字符串分词

    千次阅读 2015-01-02 14:43:12
    Java的世界里有个类型叫String,中文名就字符串。 很多时候我们需要使用它来存储, 出了基本的8个类型外,还有Date和String这两个特殊的“基本”类型. 对于字符串,我们接触的多,处理的多,却很少去总结, ...
    在Java的世界里有个类型叫String,中文名就字符串。
    

    很多时候我们需要使用它来存储, 出了基本的8个类型外,还有Date和String这两个特殊的“基本”类型.

    对于字符串,我们接触的多,处理的多,却很少去总结, 比如我们经常把用户信息存储为

    USER

    id name pass email

    1 "abc" "bb" "a@aa.com"

    AUTH

    id add modify delete
    1 true true true

    USERAUTH

    id userid authid
    1 1 1


    其实我们还可以这样存储:

    SYSTEM
    id user auth
    1 "abc","bb","a@aa.com" true,true,true

    问题就来了, 我们会想这样存储读取和保存不是很麻烦, 还有每一个的字段定义都没有。

    其实我想说,要啥字段定义,你Java中定义的对象就是字段定义,你可以随意添加和修改,而不需要修改数据库定义。

    问题又来了,那我数据库管理员可不知道你Java怎么定义的,现在要为用户A添加add操作怎么办, 好吧再添加一张数据定义表.

    DEFINE
    id column defnie
    1 user name pass email
    2 auth add modify delete

    然后, 你的java对象根据这个定义生成对象, 那么还有一个问题, 怎么搜索, 怎么删除....

    好吧,每一个定义都有其用处,比如这个数据定义适合做计算结果的存储,这样就不需要每个字段的关联,导致效率等的下降,但是也会多出维护成本,比如用户数据的变更等.

    我这人呢喜欢瞎扯,回归正题,如何做分词:

    Example1, 以逗号分隔:

    "a,b,c,d,e"



    /**
    * Splits the provided text into an array, separator specified, preserving
    * all tokens, including empty tokens created by adjacent separators.
    *
    * CSVUtil.split(null, *, true) = null
    * CSVUtil.split("", *, , true) = []
    * CSVUtil.split("a.b.c", '.', true) = ["a", "b", "c"]
    * CSVUtil.split("a...c", '.', true) = ["a", "", "", "c"]
    * CSVUtil.split("a...c", '.', false) = ["a", "c"]
    *
    * @param str
    * the string to parse
    * @param separatorChar
    * the seperator char
    * @param preserveAllTokens
    * if true, adjacent separators are treated as empty token
    * separators
    * @return the splitted string
    */
    public static String[] split(String str, char separatorChar, boolean preserveAllTokens) {
    if (str == null) {
    return null;
    }
    int len = str.length();
    if (len == 0) {
    return new String[0];
    }
    List<String> list = new ArrayList<String>();
    int i = 0, start = 0;
    boolean match = false;
    boolean lastMatch = false;
    while (i < len) {
    if (str.charAt(i) == separatorChar) {
    if (match || preserveAllTokens) {
    list.add(str.substring(start, i));
    match = false;
    lastMatch = true;
    }
    start = ++i;
    continue;
    }
    lastMatch = false;
    match = true;
    i++;
    }
    if (match || preserveAllTokens && lastMatch) {
    list.add(str.substring(start, i));
    }
    return list.toArray(new String[list.size()]);
    }


    思路: 循环每一个字符,当字符为分隔符时:

    1. any char matched?
    2. preserve(保持) token?

    当我们输保持token为false, 那么如果分割为空字符串,忽略.


    while (i < len) {
    if (str.charAt(i) == separatorChar) {
    if (match) {
    list.add(str.substring(start, i));lastMatch = true;
    match = false;
    }
    start = ++i;
    continue;
    }
    lastMatch = false;
    match = true;
    i++;
    }



    默认两个标识都为false, 当遇到非分隔符时,设置match为true, 遇到分隔符设为false,那么当match为true时,非空, 当match为false时,连续两个分隔符.


    if (match || preserveAllTokens && lastMatch) {
    list.add(str.substring(start, i));
    }



    这回处理,当最后一个逗号之后的内容,如果都之后有内容,那么lastMatch为false,match为true.
    当逗号之后没内容,那么lastMatch为true,match为false,无论有没内容都加.

    当遇到分隔符时,start=++i,表明取下一坐标开始, 而下个坐标为分隔符时, 那么i=i,也就是没有取到字符.
    这里如果preserveAllTokens为true,那么无论match是否为true,都加.
    如果preserveAllTokens为false,那么只有match为true,不是以都好结尾的才加.

    可能有人会觉得这个分词太简单了,比如可以用以下代码:


    String[] cc = "a,b,c,,d,e,f".split(",");


    JDK Source code String.split方法就能解决,多简单啊,但是这个方法不会处理最后一个逗号的值,所以自己定制的字符串分割还是很有意义的。

    当然JDK Source Code String.split还有一个扩展的方法


    String[] cc = "a,b,c,,d,e,f".split(",",7);



    * <p> The <tt>limit</tt> parameter controls the number of times the
    * pattern is applied and therefore affects the length of the resulting
    * array. If the limit <i>n</i> is greater than zero then the pattern
    * will be applied at most <i>n</i> - 1 times, the array's
    * length will be no greater than <i>n</i>, and the array's last entry
    * will contain all input beyond the last matched delimiter. If <i>n</i>
    * is non-positive then the pattern will be applied as many times as
    * possible and the array can have any length. If <i>n</i> is zero then
    * the pattern will be applied as many times as possible, the array can
    * have any length, and trailing empty strings will be discarded.


    limit: 0, will be applied as many times as possible.
    limit: 1~n, will be applied as 1~n times.
    limint: >n, the array's last entry will contain all input beyond the last matched delimiter.

    简单,这个方法会处理最后一个逗号的值,API的扩展方法。

    Example:

    String[] dd = "a,,,,,,d,e,".split(",");
    System.out.println(Arrays.toString(dd)+":"+dd.length);

    String[] ee = "a,,,,,,d,e,".split(",",8);
    System.out.println(Arrays.toString(ee)+":"+ee.length);


    String[] ff = "a,,,,,,d,e,".split(",",10);
    System.out.println(Arrays.toString(ff)+":"+ff.length);


    Output:


    [a, , , , , , d, e]:8
    [a, , , , , , d, e,]:8
    [a, , , , , , d, e, ]:9


    但是如果使用我们自己的split方法:

    .
    String[] aa = CSVUtil.split("a,,,,,,d,e,", ',', false);
    System.out.println(Arrays.toString(aa)+":"+aa.length);

    String[] bb = CSVUtil.split("a,,,,,,d,e,", ',', true);
    System.out.println(Arrays.toString(bb)+":"+bb.length);


    Output:

    [a, d, e]:3
    [a, , , , , , d, e, ]:9


    你喜欢那个API呢, 如果是我,我会选下面这个,因为字符循环,自定义的优势等等。

    具体看看JDK的实现的:

    String[] hh = null;
    String input = "abcddaeaaa";
    int limit = 100;
    int index = 0;
    boolean matchLimited = limit > 0;
    ArrayList<String> matchList = new ArrayList<String>();
    Pattern pattern = Pattern.compile("A", 2);
    Matcher m = pattern.matcher(input);
    while(m.find()) {
    if (!matchLimited || matchList.size() < limit - 1) {
    String match = input.subSequence(index, m.start()).toString();
    matchList.add(match);
    index = m.end();
    } else if (matchList.size() == limit - 1) { // last one
    String match = input.subSequence(index,
    input.length()).toString();
    matchList.add(match);
    index = m.end();
    }
    }

    // If no match was found, return this
    if (index == 0)
    hh= new String[] {input.toString()};

    // Add remaining segment
    if (!matchLimited || matchList.size() < limit)
    matchList.add(input.subSequence(index, input.length()).toString());

    // Construct result
    int resultSize = matchList.size();
    if (limit == 0){
    while (resultSize > 0 && matchList.get(resultSize-1).equals("")){
    resultSize--;
    }
    }
    String[] result = new String[resultSize];
    hh= matchList.subList(0, resultSize).toArray(result);
    //if limit is 0, then String.split at this step is delete the last "".
    // so we should be change limit to s.length.


    this is section of Pattern.split. CASE_INSENSITIVE to match.
    default String.split(","), will be ignore the last ",", cause of the construct result, this will be clean the last one of the Array,if the value is "" will be remove.

    当然想要添加最后一个也简单,limit = input.length:


    String input1 = "a,,,,,,d,e,";
    String[] ii = input1.split(",",input1.length());
    System.out.println(Arrays.toString(ii)+":"+ii.length);


    Output:

    [a, , , , , , d, e, ]:9


    as this, it is the same as the result of
    CSVUtil.split("a,,,,,,d,e,", ',', true);

    那么你现在会选哪个做字符串分割呢, JDK代码是经过千锤百炼的,所以使用JDK代码更简单,而且更稳定,效率也更高, 真的吗?

    有人说功能越简单越好, JDK的字符串功能太强大了, JDK的regex可以查找,匹配, 分割等,而且刚才的limit也不好设置吧, 而且每一次进行字符串分割都需要构建Partern/Matcher...效率肯定没有直接进行字符遍历来的直接。
    展开全文
  • java字符串分词器 StringTokenizer用法

    千次阅读 2017-09-08 19:50:58
    Java中substring方法可以分解字符串,返回的是原字符串的一个子字符串。如果要讲一个字符串分解为一个一个的单词或者标记,StringTokenizer可以帮你。 先看个例子: public static void main(String[] args)...

    Java中substring方法可以分解字符串,返回的是原字符串的一个子字符串。如果要讲一个字符串分解为一个一个的单词或者标记,StringTokenizer可以帮你。

    先看个例子:

    1. public static void main(String[] args) {  
    2.  StringTokenizer st = new StringTokenizer("www.ooobj.com"".b");  
    3.  while(st.hasMoreElements()){  
    4.  System.out.println("Token:" + st.nextToken());  
    5.  }  
    6.  }  


    输出:
    Token:www
    Token:ooo
    Token:j
    Token:com

    StringTokenizer有两个常用的方法:

    1.hasMoreElements()。这个方法和hasMoreElements()方法的用法是一样的,只是StringTokenizer为了实现Enumeration接口而实现的方法,从StringTokenizer的声明可以看到:class StringTokenizer implements Enumeration<Object>。

    2.nextElement()。这个方法和nextToken()方法的用法是一样的,返回此 StringTokenizer 的下一个标记。

    StringTokenizer的三个构造方法:

    1.StringTokenizer(String str)。默认以” \t\n\r\f”(前有一个空格,引号不是)为分割符。
    源码:
    public StringTokenizer(String str) {
    this(str, ” \t\n\r\f”, false);
    }

    实例:

    [java]  view plain  copy
     print ?
    1. public static void main(String[] args) {  
    2.  StringTokenizer st = new StringTokenizer("www ooobj com");  
    3.  while(st.hasMoreElements()){  
    4.  System.out.println("Token:" + st.nextToken());  
    5.  }  
    6.  }  


    输出:
    Token:www
    Token:ooobj
    Token:com

    2.StringTokenizer(String str, String delim)。指定delim为分割符,看第一个例子。

    3.StringTokenizer(String str, String delim, boolean returnDelims)。returnDelims为true的话则delim分割符也被视为标记。

    实例:

      public static void main(String[] args) {  

      StringTokenizer st = new StringTokenizer("www.ooobj.com", ".", true);  

      while(st.hasMoreElements()){  

      System.out.println("Token:" + st.nextToken());  

      }  

      } 

    输出:
    Token:www
    Token:.
    Token:ooobj
    Token:.
    Token:com




    展开全文
  • 1.根据词典wordDict给字符串s进行分词,返回用"|"链接的字符串 示例: 输入: s=“今天天气不错”, wordDict=[“今天”,“天天”,“天气”,“不错”,“错”] 输出∶ 今天|天气|不错 代码: package participle; ...

    1.根据词典wordDict给字符串s进行分词,返回用"|"链接的字符串

    示例:

    输入:

    s=“今天天气不错”,
    wordDict=[“今天”,“天天”,“天气”,“不错”,“错”]

    输出∶

    今天|天气|不错

    代码:

    package participle;
    
    import java.util.*;
    
    /**
     * @author :xiaotao
     * @date :2021/3/29 10:58
     * @description:
     */
    public class Participle {
        public static void main(String[] args) {
            String s = "今天天气不错";
    
            List<String> wordDict = Arrays.asList("今天", "天天", "天气", "不错", "错");
    
            String s1 = new Solution().wordBreak(s, wordDict);
            System.out.println(s1);
           
        }
    }
    
    class Solution {
        // 拆分单词
        public String wordBreak(String s, List<String> wordDict) {
            // 哈希表存储字符串s的每个下标和从该下标开始的部分可以组成的句子列表
            // 在回溯过程中如果遇到已经访问过的下标,则可以直接从哈希表得到结果,而不需要重复计算
            // 如果到某个下标发现无法匹配,则哈希表中该下标对应的是空列表
            // 因此可以对不能拆分的情况进行剪枝优化。
            Map<Integer, List<List<String>>> map = new HashMap<>();
            // 使用记忆回溯进行字符串拆分
            List<List<String>> wordBreaks = backtrack(s, s.length(), new HashSet<>(wordDict), 0, map);
            String result = "";
            for (List<String> wordBreak : wordBreaks) { // 结果添加
                for (int i = 0; i < wordBreak.size(); i++) {
                    String word = wordBreak.get(i);
                    if (i < wordBreak.size() - 1) {
                        result = result + word + "|";
                    } else {
                        result = result + word;
                    }
                }
            }
            return result;
        }
    
        public List<List<String>> backtrack(String s, int length, Set<String> wordSet,
                                            int index, Map<Integer, List<List<String>>> map) {
            if (!map.containsKey(index)) { // 判断匹配字符串的下标位置
                List<List<String>> wordBreaks = new LinkedList<>();
                if (index == length) { // 匹配到字符串末尾
                    wordBreaks.add(new LinkedList<>());
                }
                for (int i = index; i <= length; i++) { // 对剩下的字符串进行匹配
                    String word = s.substring(index, i);  // 按顺序截取其中一部分内容
                    if (wordSet.contains(word)) { // 单词表中含有字母
                        // 递归调用, 用接下来的字符串进行继续拆分
                        List<List<String>> nextWordBreaks = backtrack(s, length, wordSet, i, map);
                        for (List<String> nextWordBreak : nextWordBreaks) {
                            LinkedList<String> wordBreak = new LinkedList<String>(nextWordBreak);
                            wordBreak.offerFirst(word);
                            wordBreaks.add(wordBreak);
                        }
                    }
                }
                map.put(index, wordBreaks);
            }
            return map.get(index);
        }
    }
    
    

    运行结果:

    E:\develop\Java\jdk1.8.0_171\bin\java.exe...
    今天|天气|不错
    
    Process finished with exit code 0
    
    
    展开全文
  • 中文分词java实现

    2018-05-09 22:38:07
    所需要抽取的文本进行分词和词性的标注,将中文划分为独立存在的词, 并且辨别这些词的词性,将每一个词的词性标注在每一个词的后面。这样做可以方便我们一些需要的词的抽取,并且能更加方便的进行词频统计。
  • 字符串分词,字符串词语切割

    千次阅读 2018-09-26 14:45:16
    基本分词-BaseAnalysis 基本分词是什么 基本就是保证了最基本的分词.词语颗粒度最非常小的..所涉及到的词大约是10万左右. 基本分词速度非常快.在macAir上.能到每秒300w字每秒.同时准确率也很高.但是对于新词他的...

     

    基本分词-BaseAnalysis

    基本分词是什么

    • 基本就是保证了最基本的分词.词语颗粒度最非常小的..所涉及到的词大约是10万左右.
    • 基本分词速度非常快.在macAir上.能到每秒300w字每秒.同时准确率也很高.但是对于新词他的功能十分有限

    基本分词具有什么功能

     

    一个简单的使用方式

    package demo;
    
    import java.util.List;
    
    import org.ansj.domain.Term;
    import org.ansj.splitWord.analysis.BaseAnalysis;
     
    /**
     * @author liuchaojun
     * @date 2018-8-27 下午05:18:50
     */
    public class Test {
    	public static void main(String[] args) {
    			List<Term> parse = BaseAnalysis.parse("大家新年好!");
    			System.out.println(parse);
    	}
    }
     

    运行结果

     

    精准分词-ToAnalysis

    精准分词具有什么功能

    1. 用户自定义词典
    2. 数字识别
    3. 人名识别

    一个简单的使用方式

    /**
     * 
     */
    package demo;
    
    import java.util.List;
    
    import org.ansj.domain.Term;
    import org.ansj.splitWord.analysis.ToAnalysis;
    
    /**
     * @author liuchaojun
     * @date 2018-9-26 下午01:47:23
     */
    public class Test1 {
    	public static void main(String[] args) {
    		  List<Term> parse = ToAnalysis.parse("让战士们过一个欢乐祥和的新春佳节。");
    		    System.out.println(parse);
    
    	}
    }
    

    运行结果:

     

    nlp分词-NlpAnalysis

    nlp分词是什么

    1. nlp分词是总能给你惊喜的一种分词方式.
    2. 它可以识别出未登录词.但是它也有它的缺点.速度比较慢.稳定性差.ps:我这里说的慢仅仅是和自己的其他方式比较.应该是40w字每秒的速度吧.
    3. 个人觉得nlp的适用方式.1.语法实体名抽取.未登录词整理.只要是对文本进行发现分析等工作

    精准分词具有什么功能

    1. 用户自定义词典
    2. 数字识别
    3. 人名识别
    4. 机构名识别
    5. 新词发现

    一个简单的使用方式

    package demo;
    
    import java.util.List;
    
    import org.ansj.domain.Term;
    import org.ansj.splitWord.analysis.NlpAnalysis;
    
    /**
     * @author liuchaojun
     * @date 2018-9-26 下午02:12:19
     */
    public class Test3 {
    	public static void main(String[] args) {
    		   List<Term> parse = NlpAnalysis.parse("洁面仪配合洁面深层清洁毛孔 清洁鼻孔面膜碎觉使劲挤才能出一点点皱纹 脸颊毛孔修复的看不见啦 草莓鼻历史遗留问题没辙 脸和脖子差不多颜色的皮肤才是健康的 长期使用安全健康的比同龄人显小五到十岁 28岁的妹子看看你们的鱼尾纹");
    		   System.out.println(parse);
    	}
    }
    

    运行结果:

    面向索引的分词-IndexAnalysis

    面向索引的分词是什么

    面向索引的分词。故名思议就是适合在lucene等文本检索中用到的分词。 主要考虑以下两点

    • 召回率
      • 召回率是对分词结果尽可能的涵盖。比如对“上海虹桥机场南路” 召回结果是[上海/ns, 上海虹桥机场/nt, 虹桥/ns, 虹桥机场/nz, 机场/n, 南路/nr]
    • 准确率
      • 其实这和召回本身是具有一定矛盾性的Ansj的强大之处是很巧妙的避开了这两个的冲突 。比如我们常见的歧义句“旅游和服务”->对于一般保证召回 。大家会给出的结果是“旅游 和服 服务” 对于ansj不存在跨term的分词。意思就是。召回的词只是针对精准分词之后的结果的一个细分。比较好的解决了这个问题

    基本分词具有什么功能

    1. 用户自定义词典
    2. 数字识别
    3. 人名识别

    一个简单的使用方式

    package demo;
    
    import java.util.List;
    
    import org.ansj.domain.Term;
    import org.ansj.splitWord.analysis.IndexAnalysis;
    
    /**
     * @author liuchaojun
     * @date 2018-9-26 下午02:15:57
     */
    public class Test4 {
    	public static void main(String[] args) {
    		List<Term> parse = IndexAnalysis.parse("上海虹桥机场");
    		System.out.println(parse);
    	}
    }

    运行结果:

    用户自定义词典

    Ansj目前支持以下的公户自定义词典的操作方式.

    • 从文件中加载词典
      • 配置文件
      • 编码路径
    • 从内存操作词典
      • 增加
      • 删除
      • 修改

    同时Ansj的用户自定义词典.支持多词典.多层次的分词.对于特定领域的分词.就是一神器.O(∩_∩)O~

     

    动态添加

    直接看例子.这个功能其实在tree-split中就已经存在的.

    说明:

    1..删除只能删除用户自定义词典的词.

    2.对了分词默认把大写都转换为小写了.所以添加新词的时候要求必须是小写.

    package demo;
    import java.util.List;
    import org.ansj.domain.Term;
    import org.ansj.library.UserDefineLibrary;
    import org.ansj.splitWord.analysis.ToAnalysis;
    /**
     * @author liuchaojun
     * @date 2018-9-26 下午02:22:58 
     */
    public class DynamicWordDemo {
    	 public static void main(String[] args) {
    	        // 增加新词,中间按照'\t'隔开
    	        UserDefineLibrary.insertWord("ansj中文分词", "userDefine", 1000);
    	        List<Term> terms = ToAnalysis.parse("我觉得Ansj中文分词是一个不错的系统!我是王婆!");
    	        System.out.println("增加新词例子:" + terms);
    	        // 删除词语,只能删除.用户自定义的词典.
    	        UserDefineLibrary.removeWord("ansj中文分词");
    	        terms = ToAnalysis.parse("我觉得ansj中文分词是一个不错的系统!我是王婆!");
    	        System.out.println("删除用户自定义词典例子:" + terms);
    	}
    }

    运行结果:

    0

     

    设置辞典路径

    关于ansj分词用户自定义词典的路径设置

    第一种.正规方式

    创建library.properties 中增加

    #path of userLibrary
    userLibrary=library/userLibrary/userLibrary.dic
    ambiguityLibrary=/library/ambiguity.dic
    

    第二种 在用词典未加载前可以通过,代码方式方式来加载

    MyStaticValue.userLibrary=[你的路径]
    

    第三种,调用api加载.在程序运行的任何时间都可以.动态价值

    loadLibrary.loadLibrary(String path)方式加载
    

    路径可以是具体文件也可以是一个目录 如果是一个目录.那么会扫描目录下的dic文件自动加入词典

     

    歧义纠正辞典

    很多时候.分词发生歧异不是很好调整.用户需要更强的规则来约束所以.ansj中增加了歧异消除的一个强规则方式

    在library/ambiguity.dic

    中你会看到如下内容

    三个和尚    三个    m    和尚    n
    的确定不    的确    d    定    v    不    v
    大和尚    大    a    和尚    n
    张三和    张三    nr    和    c
    

    这里例子告诉计算机

    第一列是识别串.第二列是分词结果.奇数行是词.偶数行是词性.

    ps:这个是优先分词运行的.所以添加时候要谨慎...

    当然 ambiguity.dic 的路径你可以在分词调用前..

    用 MyStaticValue.ambiguityLibrary = "歧异词典的路径" 来设定

    歧义纠正是Ansj分词的最后最后的大招了。杀伤力巨大。谨慎使用。极可能造成其他的错误。

     

    下面给一个例子。是动态添加的。

                //歧义纠正
                Value value = new Value("川府办", "川府办", "n");
                Library.insertWord(UserDefineLibrary.ambiguityForest, value);
    
                value = new Value("京财企业务", "京财企", "nt", "业务", "j");
                Library.insertWord(UserDefineLibrary.ambiguityForest, value);
    
                System.out.println(NlpAnalysis.parse("据说川府办发的发文很厉害"));;
                System.out.println(NlpAnalysis.parse("京财企业务繁忙"));;

     

    自定义词性和停用词

    很多时候.系统的内置词性无法满足您的需求.

    你需要根据自己的规则对词语进行词性标注.

    最简单的就是用户自定义词典中的词性在分词结果中,并不是优先出现的.

    所以我们通过 FilterModifWord 来对分次结果进一步处理

    1.增加停用词的例子

    //增加两个停用词
    FilterModifWord.insertStopWord("并且") ;
    FilterModifWord.insertStopWord("但是") ;
    

    2.增加停用词性的例子

    //加入过滤词性词性
    FilterModifWord.insertStopNatures("v") ;
    

    3.以用户自定义的词性优先

    /*
     * 停用词过滤并且修正词性
     */
    List<Term> parse = ToAnalysis.parse(string) ;
    new NatureRecognition(parse).recognition() ;
    FilterModifWord.modifResult(parse) ;
    

    4.使用自定义的词典树

    /*
     * 停用词过滤并且修正词性,
     */
    public static List<Term> modifResult(List<Term> all, Forest... forests) 

     

    分词http服务

    摘要

    • ansj_seg 内置了一个用来提供分词 API 的 HttpServer,类名为 org.ansj.web.AnsjServer。
    • 启动服务

    在开发环境中,可以通过 mvn 运行分词服务:>

    mvn exec:java -Dexec.mainClass="org.ansj.web.AnsjServer" -Dexec.args="<端口号>"

    在 staging 或生产环境中,运行 org.ansj.webAnsjServer 类即可,如:

    java -classpath [jar包位置] org.ansj.app.web.AnsjServer <端口号>


     

    API 调用

    假设端口号为 8888。

    一个调用例子为:http://127.0.0.1:8888/segment?input=自然语言处理&method=to&nature=true

    input

    待分词的文本。

    method

    使用的分词方法,可以为 to, nlp 或 base。对应 ansj_seg 的 analysis 中的三种分词方法。

    默认为 to。

    nature

    是否启用词性标注,true 代表启用,false 代表禁用。

    默认为 true。


     

    如果需要一个演示界面可以直接访问

    http://127.0.0.1:[]port]/page/index.html

    就可以进行可视化操作了


     

    为了方便调用。为了不总解释我搭配好了一套系统大家可以从这里下载。

    http://yun.baidu.com/s/1dDBrec5#dir/path=%2Fansj%E5%88%86%E8%AF%8D 下载ansj_web.jar

    解压缩运行run.sh 然后访问

    展示界面:http://127.0.0.1:8888/page/index.html

    API:http://127.0.0.1:8888

     

    新词发现小工具

    1. 其实本身是一个tire树。因为分词中集成了大量的。新词识别。 比如 人名识别,机构名识别,新词发现等,这些新词的出现对分词结果起着重要的影响,如何能将这些结果整合起来。 可以想到的有两种方式,
    2. 线性链模式:以新词发现的准确率为基准,进行一步一步的合并。 比如。现识别人名,(因为人名识别的准确率相对较高)再识别机构名,然后是地名等 这个方式的优点是速度快。程序逻辑清晰。在不同识别方式上不必要担心,词语权重不一致。 但是缺点也很明显,人名识别发生错误。造成后面的识别一错再错,比如“非洲八冠王曾夺世界季军”,如果现经历人名识别。会出现“王曾夺”错误的划分为人名。
    3. 集合模式:这个方式就是利用了learntool的特性。它将所有识别出来的认为是新词的词语。都完整的加入learntool中。之后再以新词为辞典。构建最优路径。

    
      package org.ansj.demo;
    
      import org.ansj.dic.LearnTool;
      import org.ansj.domain.Nature;
      import org.ansj.splitWord.analysis.NlpAnalysis;
    
      /**
       * 新词发现工具
       * @author ansj
       *
       */
      public class LearnToolDemo {
          public static void main(String[] args) {
    
              //构建一个新词学习的工具类。这个对象。保存了所有分词中出现的新词。出现次数越多。相对权重越大。
              LearnTool learnTool = new LearnTool() ;
    
              //进行词语分词。也就是nlp方式分词,这里可以分多篇文章
              NlpAnalysis.parse("说过,社交软件也是打着沟通的平台,让无数寂寞男女有了肉体与精神的寄托。", learnTool) ;
              NlpAnalysis.parse("其实可以打着这个需求点去运作的互联网公司不应只是社交类软件与可穿戴设备,还有携程网,去哪儿网等等,订房订酒店多好的寓意", learnTool) ;
              NlpAnalysis.parse("张艺谋的卡宴,马明哲的戏",learnTool) ;
    
              //取得学习到的topn新词,返回前10个。这里如果设置为0则返回全部
              System.out.println(learnTool.getTopTree(10));
    
              //只取得词性为Nature.NR的新词
              System.out.println(learnTool.getTopTree(10,Nature.NR));
    
          }
      }
    

    关于learntool的结果保存。及重新训练

    • 有好几个朋友提出过这个问题.的确当初做这个的时候没有完整的考虑。那么让我们看看他是怎么可以迭代训练吧。我直接上代码了,因为其内部newWord结构比较复杂。所以在write的时候。我放弃了没有激活的词,很可能这些词。会在以后激活,而且放弃了这些词的词性。全部为nw,但是这个词性也可能在以后的训练中纠正。目前我觉得最简单的保存方式只有如此。完整无损保存这个功能,可能会在以后的版本实现,我最终的意思是。现这么凑合用吧。也还行问题不大 !^_^
      /**
       * 将训练结果序列写入到硬盘中
       */
      List<Entry<String, Double>> topTree = learnTool.getTopTree(0);
      StringBuilder sb = new StringBuilder();
      for (Entry<String, Double> entry : topTree) {
          sb.append(entry.getKey() + "\t" + entry.getValue()+"\n");
      }
      IOUtil.Writer("/home/ansj/temp/learnTool.snap", IOUtil.UTF8, sb.toString());
      sb = null;
    
      /**
       * reload训练结果
       */
      learnTool = new LearnTool() ;
      HashMap<String, Double> loadMap = IOUtil.loadMap("/home/ansj/temp/learnTool.snap", IOUtil.UTF8, String.class, Double.class);
      for (Entry<String, Double> entry : loadMap.entrySet()) {
          learnTool.addTerm(new NewWord(entry.getKey(), Nature.NW, entry.getValue())) ;
          learnTool.active(entry.getKey()) ;
      }
      System.out.println(learnTool.getTopTree(10));

     

    关键词抽取

    /**
     * 关键词提取的例子
     * @author ansj
     *
     */
    public class KeyWordCompuerDemo {
    public static void main(String[] args) {
        KeyWordComputer kwc = new KeyWordComputer(5);
        String title = "维基解密否认斯诺登接受委内瑞拉庇护";
        String content = "有俄罗斯国会议员,9号在社交网站推特表示,美国中情局前雇员斯诺登,已经接受委内瑞拉的庇护,不过推文在发布几分钟后随即删除。俄罗斯当局拒绝发表评论,而一直协助斯诺登的维基解密否认他将投靠委内瑞拉。  俄罗斯国会国际事务委员会主席普什科夫,在个人推特率先披露斯诺登已接受委内瑞拉的庇护建议,令外界以为斯诺登的动向终于有新进展。  不过推文在几分钟内旋即被删除,普什科夫澄清他是看到俄罗斯国营电视台的新闻才这样说,而电视台已经作出否认,称普什科夫是误解了新闻内容。  委内瑞拉驻莫斯科大使馆、俄罗斯总统府发言人、以及外交部都拒绝发表评论。而维基解密就否认斯诺登已正式接受委内瑞拉的庇护,说会在适当时间公布有关决定。  斯诺登相信目前还在莫斯科谢列梅捷沃机场,已滞留两个多星期。他早前向约20个国家提交庇护申请,委内瑞拉、尼加拉瓜和玻利维亚,先后表示答应,不过斯诺登还没作出决定。  而另一场外交风波,玻利维亚总统莫拉莱斯的专机上星期被欧洲多国以怀疑斯诺登在机上为由拒绝过境事件,涉事国家之一的西班牙突然转口风,外长马加略]号表示愿意就任何误解致歉,但强调当时当局没有关闭领空或不许专机降落。";
            Collection<Keyword> result = kwc.computeArticleTfidf(title, content);
                System.out.println(result);
        }
    }

     

    词性标注

    • Ansj词性标注是基于HMM的。

    主要利用了ngram的方式,相对而言作的还是比较粗糙

    • 词性标注的规范

    说句实话,这个自由度一直很高,因为既要支持用户自定义辞典。而用户的词性关我屁事。所以没有一个完整的统一。但是在实际使用中我们还是尽量以北大标注为准,在另一个文档中,有一份词性说明。我自己增加了nw词性,这个词性意思是是一个新词,但是具体是什么。我不知道。

    • 什么地方需要词性标注

    除了nlpanalysis 自带词性标注。其他的方式都是需要词性标注的。词性标注的方式是以工具类的形式调用。下面是调用代码,可以看到我们是利用new NatureRecognition(terms).recognition();对分词结果进行的标注。

        package org.ansj.demo;
    
        import java.io.IOException;
        import java.util.List;
    
        import org.ansj.domain.Term;
        import org.ansj.recognition.NatureRecognition;
        import org.ansj.splitWord.analysis.ToAnalysis;
    
        /**
         * 词性标注
         * 
         * @author ansj
         * 
         */
        public class NatureDemo {
            public static void main(String[] args) throws IOException {
                List<Term> terms = ToAnalysis.parse("Ansj中文分词是一个真正的ict的实现.并且加入了自己的一些数据结构和算法的分词.实现了高效率和高准确率的完美结合!");
                new NatureRecognition(terms).recognition(); //词性标注
                System.out.println(terms);
            }
        }
    
    • 我只想用ansj的词性标注。我没有分词结果
    
        package org.ansj.demo;    
        import java.util.Arrays;
        import java.util.List;
        import org.ansj.domain.Term;
        import org.ansj.recognition.NatureRecognition;
    
        /**
         * 对非ansj的分词结果进行词性标注
         * @author ansj
         *
         */
        public class NatureTagDemo {
            public static void main(String[] args) {
                String[] strs = {"对", "非", "ansj", "的", "分词", "结果", "进行", "词性", "标注"} ;
                List<String> lists = Arrays.asList(strs) ;
                List<Term> recognition = NatureRecognition.recognition(lists, 0) ;
                System.out.println(recognition);
            }
        }

     

    tree-split

    • tree-split是一个小巧好用的。tire树数据库。
    • 里面封装了我一些常用的工具类。比如IOUtil 。 StringUtil。
    • tire树就不解释了。也就是词典树,个人认为是最好的分词数据结构。没有之一。
    • tree-split 中的tire采用首字hash 。次字二分查找的方式。同时也支持参数可配置的形式。

    下面是tree-split的一个使用说明

    
            /**
             * 词典的构造.一行一个词后面是参数.可以从文件读取.可以是read流.
             */
            String dic = "中国\t1\tzg\n人名\t2\n中国人民\t4\n人民\t3\n孙健\t5\nCSDN\t6\njava\t7\njava学习\t10\n";
            Forest forest = Library.makeForest(new BufferedReader(new StringReader(dic)));
    
            /**
             * 删除一个单词
             */
            Library.removeWord(forest, "中国");
            /**
             * 增加一个新词
             */
            Library.insertWord(forest, "中国人");
            String content = "中国人名识别是中国人民的一个骄傲.孙健人民在CSDN中学到了很多最早iteye是java学习笔记叫javaeye但是java123只是一部分";
            GetWord udg = forest.getWord(content);
    
            String temp = null;
            while ((temp = udg.getFrontWords()) != null)
                System.out.println(temp + "\t\t" + udg.getParam(1) + "\t\t" + udg.getParam(2));
    

    jar包下载地址:

    http://maven.ansj.org/org/ansj/tree_split/

    maven

    • 第一步在你的pom.xml中加入.
    <project>
        <repositories>
            <repository>
                <id>mvn-repo</id>
                <url>http://maven.ansj.org/</url>
            </repository>
        </repositories>
    </project>
    1. 在dependencies标签中粘贴如下:(其实version 以最新的为标准.)
        <dependencies>
            <dependency>
                <groupId>org.ansj</groupId>
                <artifactId>tree_split</artifactId>
                <version>1.2</version>
            </dependency>
        </dependencies>

    获得源码

    https://github.com/ansjsun/tree_split

     

    Ansj In Lucene

    • Ansj目前有了lucene 什么版本的插件:
      • lucene3.x
      • lucene4.x

    对于3.x之前的版本,我表示不会写相关的jar了,lucene的分词插件不是很难写,如果非要说难写就是因为他没有一个很好的文档和说明,里面暗坑比较多。

    • 如何获得lucene插件的jar包:

    • 你可以从我的maven仓库中下载http://maven.ansj.org/org/ansj/ 打开这个

      找到 ansj_lucene3_plug/ , ansj_lucene4_plug/ 从里面下载jar包把。maven的话同理。不多阐述

            //实际使用中jar最好是最新版本的,需要这三个jar。。。
            http://maven.ansj.org/org/ansj/ansj_lucene4_plug/1.3/ansj_lucene4_plug-1.3.jar
      
            http://maven.ansj.org/org/ansj/ansj_seg/1.x/ansj_seg-1.3-min.jar
      
            http://maven.ansj.org/org/ansj/tree_split/1.x/tree_split-1.2.jar
      
    • 如何用maven集成

       <dependency>
                <groupId>org.ansj</groupId>
                <artifactId>ansj_seg</artifactId>
                <version>1.3</version>
             <classifier>min</classifier>
            </dependency>
            <dependency>
                <groupId>org.ansj</groupId>
                <artifactId>ansj_lucene4_plug</artifactId>
                <version>1.3</version>
            </dependency>
      
    • 如何获得Ansj lucene插件的源码:

            插件源码我已经集合到ansj_seg的项目中了。在plug目录下有这两个项目的源码。并且也是maven项目。你可以直接作为maven导入。

    • 使用例子:

     

    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.Reader;
    import java.io.StringReader;
    import java.util.Date;
    import java.util.HashSet;
    import java.util.ResourceBundle;
    import love.cq.util.IOUtil;
    import org.ansj.lucene.util.PorterStemmer;
    import org.apache.lucene.analysis.Analyzer;
    import org.apache.lucene.analysis.Token;
    import org.apache.lucene.analysis.TokenStream;
    import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
    import org.apache.lucene.document.Document;
    import org.apache.lucene.document.Field;
    import org.apache.lucene.index.CorruptIndexException;
    import org.apache.lucene.index.IndexWriter;
    import org.apache.lucene.index.IndexWriterConfig;
    import org.apache.lucene.queryParser.ParseException;
    import org.apache.lucene.queryParser.QueryParser;
    import org.apache.lucene.search.IndexSearcher;
    import org.apache.lucene.search.Query;
    import org.apache.lucene.search.TopDocs;
    import org.apache.lucene.search.highlight.Highlighter;
    import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
    import org.apache.lucene.search.highlight.QueryScorer;
    import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
    import org.apache.lucene.store.Directory;
    import org.apache.lucene.store.LockObtainFailedException;
    import org.apache.lucene.store.RAMDirectory;
    import org.apache.lucene.util.Version;
    import org.junit.Test;
    public class AnsjAnalysisTest {
        @Test
        public void test() throws IOException {
            Token nt = new Token();
            Analyzer ca = new AnsjAnalysis();
            Reader sentence = new StringReader(
                    "\n\n\n\n\n\n\n我从小就不由自主地认为自己长大以后一定得成为一个象我父亲一样的画家, 可能是父母潜移默化的影响。其实我根本不知道作为画家意味着什么,我是否喜欢,最重要的是否适合我,我是否有这个才华。其实人到中年的我还是不确定我最喜欢什么,最想做的是什么?我相信很多人和我一样有同样的烦恼。毕竟不是每个人都能成为作文里的宇航员,科学家和大教授。知道自己适合做什么,喜欢做什么,能做好什么其实是个非常困难的问题。"

     

                        + "幸运的是,我想我的孩子不会为这个太过烦恼。通过老大,我慢慢发现美国高中的一个重要功能就是帮助学生分析他们的专长和兴趣,从而帮助他们选择大学的专业和未来的职业。我觉得帮助一个未成形的孩子找到她未来成长的方向是个非常重要的过程。"
                        + "美国高中都有专门的职业顾问,通过接触不同的课程,和各种心理,个性,兴趣很多方面的问答来帮助每个学生找到最感兴趣的专业。这样的教育一般是要到高年级才开始, 可老大因为今年上计算机的课程就是研究一个职业走向的软件项目,所以她提前做了这些考试和面试。看来以后这样的教育会慢慢由电脑来测试了。老大带回家了一些试卷,我挑出一些给大家看看。这门课她花了2个多月才做完,这里只是很小的一部分。"
                        + "在测试里有这样的一些问题:"
                        + "你是个喜欢动手的人吗? 你喜欢修东西吗?你喜欢体育运动吗?你喜欢在室外工作吗?你是个喜欢思考的人吗?你喜欢数学和科学课吗?你喜欢一个人工作吗?你对自己的智力自信吗?你的创造能力很强吗?你喜欢艺术,音乐和戏剧吗?  你喜欢自由自在的工作环境吗?你喜欢尝试新的东西吗? 你喜欢帮助别人吗?你喜欢教别人吗?你喜欢和机器和工具打交道吗?你喜欢当领导吗?你喜欢组织活动吗?你什么和数字打交道吗?");
        TokenStream ts = ca.tokenStream("sentence", sentence);
    
        System.out.println("start: " + (new Date()));
        long before = System.currentTimeMillis();
        while (ts.incrementToken()) {
            System.out.println(ts.getAttribute(CharTermAttribute.class));
        }
        ts.close();
        long now = System.currentTimeMillis();
        System.out.println("time: " + (now - before) / 1000.0 + " s");
    }
    
    @Test
    public void indexTest() throws CorruptIndexException, LockObtainFailedException, IOException, ParseException {
        HashSet<String> hs = new HashSet<String>();
        BufferedReader reader2 = IOUtil.getReader(ResourceBundle.getBundle("library").getString("stopLibrary"), "UTF-8");
        String word = null;
        while ((word = reader2.readLine()) != null) {
            hs.add(word);
        }
        Analyzer analyzer = new AnsjAnalysis(hs,false);
        Directory directory = null;
        IndexWriter iwriter = null;
    
        BufferedReader reader = IOUtil.getReader("/Users/ansj/Desktop/未命名文件夹/indextest.txt", "UTF-8");
        String temp = null;
        StringBuilder sb = new StringBuilder();
        while ((temp = reader.readLine()) != null) {
            sb.append(temp);
            sb.append("\n");
        }
        reader.close();
        String text = sb.toString();
    
        text = "开源项目管理你喜欢在室外工作吗?你是个喜欢思考的人吗?你喜欢数学和科学课吗?你喜欢一个人工作吗?你对自己的智力自信吗?你的创造能力很强吗?你喜欢艺术,音乐和戏剧吗?  你喜欢自由自在的工作环境吗?你喜欢尝试新的东西吗? 你喜欢帮助别人吗?你喜欢教别人吗?你喜欢和机器和工具打交道吗?你喜欢当领导吗?你喜欢组织活动吗?你什么和数字打交道吗?";
    
        IndexWriterConfig ic = new IndexWriterConfig(Version.LUCENE_32, analyzer);
        // 建立内存索引对象
        directory = new RAMDirectory();
        iwriter = new IndexWriter(directory, ic);
        // BufferedReader reader =
        // IOUtil.getReader("/Users/ansj/Documents/快盘/分词/语料/1998年人民日报分词语料_未区分.txt",
        // "GBK");
        // String temp = null;
        // while ((temp = reader.readLine()) != null) {
        // addContent(iwriter, temp);
        // }
        addContent(iwriter, text);
        addContent(iwriter, text);
        addContent(iwriter, text);
        addContent(iwriter, text);
        iwriter.commit();
        iwriter.close();
    
        System.out.println("索引建立完毕");
    
        search(analyzer, directory, "室外工作");
    }
    
    private Analyzer ansjHeightAnalyzer = new AnsjAnalysis();
    
    private void search(Analyzer analyzer, Directory directory, String queryStr) throws CorruptIndexException, IOException, ParseException {
        IndexSearcher isearcher;
        // 查询索引
        isearcher = new IndexSearcher(directory);
        QueryParser tq = new QueryParser(Version.LUCENE_32, "text", ansjHeightAnalyzer);
        Query query = tq.parse(queryStr);
        System.out.println(query);
        TopDocs hits = isearcher.search(query, 5);
        System.out.println(queryStr + ":共找到" + hits.totalHits + "条记录!");
        for (int i = 0; i < hits.scoreDocs.length; i++) {
            int docId = hits.scoreDocs[i].doc;
            Document document = isearcher.doc(docId);
            System.out.println(toHighlighter(ansjHeightAnalyzer, query, document));
        }
    }
    
    /**
     * 高亮设置
     * 
     * @param query
     * @param doc
     * @param field
     * @return
     */
    private String toHighlighter(Analyzer analyzer, Query query, Document doc) {
        String field = "text";
        try {
            SimpleHTMLFormatter simpleHtmlFormatter = new SimpleHTMLFormatter("<font color=\"red\">", "</font>");
            Highlighter highlighter = new Highlighter(simpleHtmlFormatter, new QueryScorer(query));
            TokenStream tokenStream1 = analyzer.tokenStream("text", new StringReader(doc.get(field)));
            String highlighterStr = highlighter.getBestFragment(tokenStream1, doc.get(field));
            return highlighterStr == null ? doc.get(field) : highlighterStr;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidTokenOffsetsException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    private void addContent(IndexWriter iwriter, String text) throws CorruptIndexException, IOException {
        Document doc = new Document();
        doc.add(new Field("text", text, Field.Store.YES, Field.Index.ANALYZED));
        iwriter.addDocument(doc);
    }
    @Test
    public void poreterTest() {
        PorterStemmer ps = new PorterStemmer();
        System.out.println(ps.stem("apache"));
    }
    

    Ansj In Solr

    已经有热心的大牛,帮我完成了这个。我直接粘贴他的git地址了。有啥问题直接找他与我无关^_^

    https://github.com/lgnlgn/ansj4solr

    在这里感谢@梁山伯 帅哥。。。

     

    Ansj In Elasticsearch

    推荐es神器。也是我最喜欢用的一个搜索框架。

    已经有热心的大牛,帮我完成了这个。我直接粘贴他的git地址了。有啥问题直接找他与我无关^_^

    https://github.com/4onni/elasticsearch-analysis-ansj

    在这里感谢@4onni 帅哥。。。

     

    词性说明

    汉语文本词性标注标记集

    # 1. 名词  (1个一类,7个二类,5个三类)
    名词分为以下子类:
    n 名词
    nr 人名
    nr1 汉语姓氏
    nr2 汉语名字
    nrj 日语人名
    nrf 音译人名
    ns 地名
    nsf 音译地名
    nt 机构团体名
    nz 其它专名
    nl 名词性惯用语
    ng 名词性语素
    nw 新词
    # 2. 时间词(1个一类,1个二类)
    t 时间词
    tg 时间词性语素
    # 3. 处所词(1个一类)
    s 处所词
    # 4. 方位词(1个一类)
    f 方位词
    # 5. 动词(1个一类,9个二类)
    v 动词
    vd 副动词
    vn 名动词
    vshi 动词“是”
    vyou 动词“有”
    vf 趋向动词
    vx 形式动词
    vi 不及物动词(内动词)
    vl 动词性惯用语
    vg 动词性语素
    # 6. 形容词(1个一类,4个二类)
    a 形容词
    ad 副形词
    an 名形词
    ag 形容词性语素
    al 形容词性惯用语
    # 7. 区别词(1个一类,2个二类)
    b 区别词
    bl 区别词性惯用语
    # 8. 状态词(1个一类)
    z 状态词
    # 9. 代词(1个一类,4个二类,6个三类)
    r 代词
    rr 人称代词
    rz 指示代词
    rzt 时间指示代词
    rzs 处所指示代词
    rzv 谓词性指示代词
    ry 疑问代词
    ryt 时间疑问代词
    rys 处所疑问代词
    ryv 谓词性疑问代词
    rg 代词性语素
    # 10. 数词(1个一类,1个二类)
    m 数词
    mq 数量词
    # 11. 量词(1个一类,2个二类)
    q 量词
    qv 动量词
    qt 时量词
    # 12. 副词(1个一类)
    d 副词
    # 13. 介词(1个一类,2个二类)
    p 介词
    pba 介词“把”
    pbei 介词“被”
    # 14. 连词(1个一类,1个二类)
    c 连词
     cc 并列连词
    # 15. 助词(1个一类,15个二类)
    u 助词
    uzhe 着
    ule 了 喽
    uguo 过
    ude1 的 底
    ude2 地
    ude3 得
    usuo 所
    udeng 等 等等 云云
    uyy 一样 一般 似的 般
    udh 的话
    uls 来讲 来说 而言 说来
    uzhi 之
    ulian 连 (“连小学生都会”)
    # 16. 叹词(1个一类)
    e 叹词
    # 17. 语气词(1个一类)
    y 语气词(delete yg)
    # 18. 拟声词(1个一类)
    o 拟声词
    # 19. 前缀(1个一类)
    h 前缀
    # 20. 后缀(1个一类)
    k 后缀
    # 21. 字符串(1个一类,2个二类)
    x 字符串
     xx 非语素字
     xu 网址URL
    # 22. 标点符号(1个一类,16个二类)
    w 标点符号
    wkz 左括号,全角:( 〔  [  {  《 【  〖〈   半角:( [ { <
    wky 右括号,全角:) 〕  ] } 》  】 〗 〉 半角: ) ] { >
    wyz 左引号,全角:“ ‘ 『 
    wyy 右引号,全角:” ’ 』
    wj 句号,全角:。
    ww 问号,全角:? 半角:?
    wt 叹号,全角:! 半角:!
    wd 逗号,全角:, 半角:,
    wf 分号,全角:; 半角: ;
    wn 顿号,全角:、
    wm 冒号,全角:: 半角: :
    ws 省略号,全角:……  …
    wp 破折号,全角:——   --   ——-   半角:---  ----
    wb 百分号千分号,全角:% ‰   半角:%
    wh 单位符号,全角:¥ $ £  °  ℃  半角:$

    项目的文档地址:http://nlpchina.github.io/ansj_seg/ 

    展开全文
  • 使用java进行分词处理

    千次阅读 2019-09-01 14:26:53
    使用java进行中文分词,首先需要几个jar包,分别是 IKAnalyzer2012_u6.jar,lucene-analyzers-3.6.1.jar,lucene-core-3.6.1.jar和lucene-highlighter-3.6.1.jar。下载jar包的链接为:结巴分词对应的jar包 程序...
  • Java字符串之split方法

    2021-07-03 20:55:36
    正则表达式由普通字符以及特殊字符组成的文字模式; 正则表达式可以用来搜索、编辑和处理文本。 1.1 常用语法 1.1.1 字符范围 [xyz] : 表示可能是x,可能是y,也可能是z; [^xyz] : 表示表示x,y,z中的任意一个; [a...
  • 中文分词应用很广泛,网上也有很多开源项目,下面这篇文章主要给大家介绍了关于java中文分词之正向最大匹配法的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
  • 该算法是基于分词词典实现,从字符串左侧进行分割匹配,如果词典存在则返回分割出来的词语并将该词从之前的字符串中切除,循环进行切割直到字符串大小为0。
  • 需要两个jar包 ansj_seg.jar nlp-lang public class Word{ public static void main(String[] args) { ... String str = "你微微地笑着,不同我说什么话。而我觉得,为了这个,我已等待得很久了。...
  • 设定字符串为“张三,你好,我是李四” 产生张三的密钥(keyPairZhang) 张三生成公钥(publicKeyZhang)并发送给李四,这里发送的是公钥的数组字节 通过网络或磁盘等方式,把公钥编码传送给李四,李四接收到张三编码后...
  • Java中String的分词方法split的使用

    千次阅读 2014-11-11 09:41:21
    方法分隔字符串时,分隔符如果用到一些特殊字符,可能会得不到我们预期的结果。 我们看 jdkdoc 中说明 publicString[] split(String regex) Splits this string around matches ofthe given regular ...
  • (java)字符串的相似度

    千次阅读 2016-09-19 09:39:43
    两个字符串的相似度定义为:将一个字符串转换成另外一个字符串的代价(通过插入、删除、替换三种方式转换),转换的代价越高则说明两个字符串的相似度越低。 如:snowy与sunny,转换方式有  变换1:   S - N O W ...
  • Java字符串变成对应正则

    千次阅读 2018-08-15 11:08:36
    有时候, 我们不想动脑筋根据某个内容来写对应正则, 这个时候, 我们就想, 如果直接把这段子复制一下, 得到对应的正则该多好.为了多偷一会懒, 所以写一个简单的实现.  大家都是明白人, 直接上代码, 有些说明我已经...
  • 报错的原因是Split方法底层是正则表达,特殊字符需要转义处理才可以。以下是split()的源码 public String[] split(String regex) { return split(regex, 0); } public String[] split(String regex, int ...
  • java String:字符串及正则表达式

    千次阅读 2018-03-30 11:33:28
    创建字符串public class Test { private static final String ABC = "abc"; public static void main(String[] args) { String s1 = "abc"; String s2 = new String("abc"); ...
  • 分词字符串计算 代码如下: public static double similarScoreCos(String text1, String text2){ if(text1 == null || text2 == null){ //只要有一个文本为null,规定相似度分值为0,表示完全不相等 ...
  • java正则替换字符串的高级应用

    千次阅读 2016-06-16 16:42:43
    java正则替换字符串的高级应用,正则分组正则表达式的强大不再多少,基础语法可以参考网上其他文章,本文仅介绍java中利用正则对字符串进行替换。 需求场景:需将字符串“title:大学生#END# AND text:北京#END# AND...
  • 中文分词-词典逆向最大匹配法 测试环境 windows 10 ...4、 input长度是否大于 MAX, 如果是,设置尝试匹配词语token = input后MAX个字符, 否则 token = input 5、 是否有:token的长度大于1并且token
  • 业务场景是客户在业务办理时候需要提交一个材料列表,材料会入材料库,下次客户再来办理业务时候输入客户的身份证,会通过材料库...1.以下是两个词进行处理的核心算法 package com.ikanalyzer; import java...
  • 利用正则表达式获取字符串中想要的值: 获取符串场景: 你好呀(嘻嘻) 我需要获取“嘻嘻” 该如何获取呢? 1.通过正则表达式获取: String str = "你好呀(嘻嘻)"; Pattern p = Pattern.compile("\\(([^\\)]+)"); ...
  • Java字符串中英文识别

    千次阅读 2015-07-18 23:20:45
    * 判断字符串是否为英文 * @author shore * @date 20150701 * @param str * @return */ public static boolean isCnorEn(String str) { for (int i = 0; i < str.length(); i++) { if(str.charAt(i) >=...
  • StringTokenizer 字符串分词器,用于将字符串进行分割和遍历,非常地方便 一、学习一个类先学习它的构造方法.此处3个构造方法。 看文档。 3个构造方法 1. StringTokenizer stringTokenizer = new StringTokenizer...
  • 有一个输入字符串,例如:String s=”welcome to ***”. 词中间有空格,请统计每个词出现的次数,并按出现次数多少排序输出。 以下代码分别是两种方法实现: public class Demo { public static void main...
  • StringTokenizer是字符串分隔解析类型,属于:java.util包。 StringTokenizer是java中object类的一个子类,继承自 Enumeration接口。此类允许一个应用程序进入一个令牌(tokens),而且StringTokenizer类用起来比...
  • 1--java字符串学习

    千次阅读 2016-12-24 19:19:44
    字符串学习(其他数据类型操作同C语言) 1.字符串学习一开始都是这个经典的例子: String str1 = "hello world"; String str2 = "hello world"; String str3 = new String("hello world"); System.out.println...
  • simhash算法对字符串计算权重时,中文要做特殊操作,及先分词,请自行下载sanford中文分词jar包及中文分词库
  • 借鉴hashmap算法找出可以hash的key值,因为我们使用的simhash是局部敏感哈希,这个算法的特点是只要相似的字符串只有个别的位数是有差别变化。那这样我们可以推断两个相似的文本,至少有16位的simhash是一样的。具体...
  • java中文分词的简单实现

    万次阅读 多人点赞 2018-12-03 11:33:30
    java中文分词的简单实现中文分词算法算法思路算法实现代码及注释评价结语 中文分词 通俗来讲,中文分词是指将一句中文句子中的所有...基于字符串匹配的分词方法; 基于理解的分词方法; 基于统计的分词方法。 其中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,549
精华内容 6,219
关键字:

java对字符串进行分词

java 订阅