精华内容
下载资源
问答
  • 主要介绍了Java实现的最大匹配分词算法,简单说明了最大匹配分词算法的原理并结合具体实例形式最大匹配分词算法的实现方法与相关注意事项,需要的朋友可以参考下
  • 主要介绍了Java实现的双向匹配分词算法,结合完整实例形式详细分析了双向匹配分词算法的原理与java实现技巧,需要的朋友可以参考下
  • 算法是基于分词词典实现,从字符串左侧进行分割匹配,如果词典存在则返回分割出来的词语并将该词从之前的字符串中切除,循环进行切割直到字符串大小为0。
  • java分词算法, 正向匹配,可以实现中文分词处理
  • java中文分词算法

    千次阅读 2018-04-13 09:45:22
    我想只要是学过数据库的孩纸,不管是mysql,还是sqlsever,一提到查找,本能的想到的便是like关键字,其实去转盘网(分类模式)之前也是采用这种算法,但我可以告诉大家一个很不幸的事情,like匹配其实会浪费大量的...

    我想只要是学过数据库的孩纸,不管是mysql,还是sqlsever,一提到查找,本能的想到的便是like关键字,其实去转盘网分类模式)之前也是采用这种算法,但我可以告诉大家一个很不幸的事情,like匹配其实会浪费大量的有用资源,原因这里不说了请自己想一想,我们还是直接摆事实验证。

       现在用去转盘网搜:hello 找个单词,如下:

       http://www.quzhuanpan.com/source/search.action?q=hello&currentPage=1

    翻页你会发现只要是包含hello的单词都找到了,但是如果你用like的话是不会有这个效果的,不信让我们再看一下,还好他来说电影网的分词算法我还没来得及修改,还可以看到现象:

       http://www.talaishuo.com/searchResult.do?searchFileName=hello

    你会发现只有开始包含hello这个字段的搜索串才能得到匹配,这就问题来了,数据库中大量的资源岂不是白白浪费了,不过没事,伟大的人类还是很聪明的,发明了分词,分词的原理我就不讲了,请自己百度吧,还是直接上代码,提示,这里需要四个jar包作为工具,我先上传的去转盘,想要做分词的请先下载:

       分词包下载地址1

       分词包下载地址2

    另外附上2篇有用的博客:百度网盘爬虫 百度图片爬虫

    [java]  view plain  copy
    1. package com.tray.indexData;  
    2. import java.io.File;  
    3. import java.io.IOException;  
    4. import java.io.StringReader;  
    5. import java.math.BigInteger;  
    6. import java.util.ArrayList;  
    7. import java.util.HashMap;  
    8. import java.util.List;  
    9. import java.util.Map;  
    10.    
    11. import org.apache.lucene.analysis.Analyzer;  
    12. import org.apache.lucene.analysis.TokenStream;  
    13. import org.apache.lucene.document.Document;  
    14. import org.apache.lucene.document.Fieldable;  
    15. import org.apache.lucene.index.CorruptIndexException;  
    16. import org.apache.lucene.index.IndexReader;  
    17. import org.apache.lucene.index.IndexWriter;  
    18. import org.apache.lucene.index.IndexWriterConfig;  
    19. import org.apache.lucene.index.IndexWriterConfig.OpenMode;  
    20. import org.apache.lucene.index.Term;  
    21. import org.apache.lucene.queryParser.MultiFieldQueryParser;  
    22. import org.apache.lucene.queryParser.QueryParser;  
    23. import org.apache.lucene.search.IndexSearcher;  
    24. import org.apache.lucene.search.PrefixQuery;  
    25. import org.apache.lucene.search.Query;  
    26. import org.apache.lucene.search.ScoreDoc;  
    27. import org.apache.lucene.search.TermQuery;  
    28. import org.apache.lucene.search.TopDocs;  
    29. import org.apache.lucene.search.TopScoreDocCollector;  
    30. import org.apache.lucene.search.WildcardQuery;  
    31. import org.apache.lucene.search.highlight.Highlighter;  
    32. import org.apache.lucene.search.highlight.QueryScorer;  
    33. import org.apache.lucene.search.highlight.SimpleHTMLFormatter;  
    34. import org.apache.lucene.store.Directory;  
    35. import org.apache.lucene.store.FSDirectory;  
    36. import org.apache.lucene.util.Version;  
    37. import org.wltea.analyzer.lucene.IKAnalyzer;  
    38.    
    39. import com.tray.bean.SerachResult;  
    40. import com.tray.common.tools.DateFormater;  
    41.    
    42. public class LuceneSearch {  
    43.        
    44.     private static String DISC_URL = "/home/indexData/data";  
    45.        
    46.     static {  
    47.         String os = System.getProperty("os.name");    
    48.         if(os.toLowerCase().startsWith("win")){    
    49.             DISC_URL = "E:\\indexData\\data";   
    50.         }  
    51.         else{  
    52.             DISC_URL ="/home/indexData/data";  
    53.         }  
    54.     }  
    55.            
    56.     //指定分词器   
    57.     private Analyzer analyzer=new IKAnalyzer();   
    58.     private static Directory directory;  
    59.     //配置  
    60.     private static IndexWriterConfig iwConfig;  
    61.     //配置IndexWriter  
    62.     private static IndexWriter writer;    
    63.     private static File indexFile = null;    
    64.        
    65.     private static Version version = Version.LUCENE_36;  
    66.        
    67.     private final int PAPGESIZE=10;  
    68.    
    69.     /** 
    70.      * 全量索引 
    71.      * @Author haoning 
    72.      */  
    73.     public void init() throws Exception {  
    74.            
    75.         try {  
    76.             indexFile = new File(DISC_URL);  
    77.             if (!indexFile.exists()) {  
    78.                 indexFile.mkdir();  
    79.             }  
    80.             directory=FSDirectory.open(indexFile);    
    81.             //配置IndexWriterConfig    
    82.             iwConfig = new IndexWriterConfig(version,analyzer);    
    83.             iwConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);    
    84.                 //创建写索引对象    
    85.             writer = new IndexWriter(directory,iwConfig);     
    86.         } catch (Exception e) {  
    87.         }  
    88.     }  
    89.        
    90.     public void closeWriter(){  
    91.         try {  
    92.             writer.close();  
    93.         } catch (CorruptIndexException e) {  
    94.             e.printStackTrace();  
    95.         } catch (IOException e) {  
    96.             e.printStackTrace();  
    97.         }  
    98.     }  
    99.        
    100.     public void commit(){  
    101.            
    102.         try {  
    103.             writer.commit();  
    104.         } catch (CorruptIndexException e) {  
    105.             e.printStackTrace();  
    106.         } catch (IOException e) {  
    107.             e.printStackTrace();  
    108.         }  
    109.     }  
    110.        
    111.     /** 
    112.      * 一个一个索引 
    113.      * @Author haoning 
    114.      */  
    115.     public void singleIndex(Document doc) throws Exception {  
    116.         writer.addDocument(doc);  
    117.     }  
    118.        
    119.     /** 
    120.      * 一个跟新 
    121.      * @Author haoning 
    122.      */  
    123.     public void singleUpdate(Document doc) throws Exception {  
    124.         Term term = new Term("url", doc.get("url"));  
    125.         writer.updateDocument(term,doc);  
    126.     }  
    127.        
    128.     /** 
    129.      * 全量索引 
    130.      * @Author haoning 
    131.      */  
    132.     public void fullIndex(Document[] documentes) throws Exception {  
    133.            
    134.         writer.deleteAll();  
    135.         for (Document document : documentes) {  
    136.             writer.addDocument(document);  
    137.         }  
    138.         writer.commit();  
    139.     }  
    140.        
    141.     /** 
    142.      * 根据id删除索引 
    143.      * @Author haoning 
    144.      */  
    145.     public void deleteIndex(Document document)throws Exception{  
    146.         Term term = new Term("url", document.get("url"));//url才是唯一标志  
    147.         writer.deleteDocuments(term);  
    148.         writer.commit();  
    149.     }  
    150.        
    151.     /** 
    152.      * 根据id增量索引 
    153.      * @Author haoning 
    154.      */  
    155.     public void updateIndex(Document[] documentes) throws Exception{  
    156.         for (Document document : documentes) {  
    157.             Term term = new Term("url", document.get("url"));  
    158.             writer.updateDocument(term, document);  
    159.         }  
    160.         writer.commit();  
    161.     }  
    162.        
    163.     /** 
    164.      * 直接查询 
    165.      * @Author haoning 
    166.      */  
    167.     public void simpleSearch(String filedStr,String queryStr,int page, int pageSize) throws Exception{  
    168.         File indexDir = new File(DISC_URL);    
    169.         //索引目录    
    170.         Directory dir=FSDirectory.open(indexDir);    
    171.         //根据索引目录创建读索引对象    
    172.         IndexReader reader = IndexReader.open(dir);    
    173.         //搜索对象创建    
    174.         IndexSearcher searcher = new IndexSearcher(reader);  
    175.         TopScoreDocCollector topCollector = TopScoreDocCollector.create(searcher.maxDoc(), false);  
    176.            
    177.         Term term = new Term(filedStr, queryStr);  
    178.         Query query = new TermQuery(term);  
    179.         searcher.search(query, topCollector);  
    180.         ScoreDoc[] docs = topCollector.topDocs((page-1)*pageSize, pageSize).scoreDocs;  
    181.            
    182.         printScoreDoc(docs, searcher);  
    183.     }  
    184.        
    185.     /** 
    186.      * 高亮查询 
    187.      * @Author haoning 
    188.      */  
    189.     public Map<String, Object> highLightSearch(String filed,String keyWord,int curpage, int pageSize) throws Exception{  
    190.         List<SerachResult> list=new ArrayList<SerachResult>();  
    191.         Map<String,Object> map = new HashMap<String,Object>();  
    192.         if (curpage <= 0) {  
    193.             curpage = 1;  
    194.         }  
    195.         if (pageSize <= 0 || pageSize>20) {  
    196.              pageSize = PAPGESIZE;  
    197.         }  
    198.         File indexDir = new File(DISC_URL); //索引目录     
    199.         Directory dir=FSDirectory.open(indexDir);//根据索引目录创建读索引对象      
    200.         IndexReader reader = IndexReader.open(dir);//搜索对象创建      
    201.         IndexSearcher searcher = new IndexSearcher(reader);  
    202.            
    203.         int start = (curpage - 1) * pageSize;  
    204.            
    205.         Analyzer analyzer = new IKAnalyzer(true);  
    206.         QueryParser queryParser = new QueryParser(Version.LUCENE_36, filed, analyzer);  
    207.         queryParser.setDefaultOperator(QueryParser.AND_OPERATOR);  
    208.         Query query = queryParser.parse(keyWord);  
    209.            
    210.         int hm = start + pageSize;  
    211.         TopScoreDocCollector res = TopScoreDocCollector.create(hm, false);  
    212.         searcher.search(query, res);  
    213.            
    214.         SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<span style='color:red'>""</span>");  
    215.         Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));  
    216.            
    217.         long amount = res.getTotalHits();  
    218.         //long pages = (rowCount - 1) / pageSize + 1; //计算总页数  
    219.            
    220.         map.put("amount",amount);//总共多少条记录  
    221.            
    222.         TopDocs tds = res.topDocs(start, pageSize);  
    223.         ScoreDoc[] sd = tds.scoreDocs;  
    224.            
    225.         for (int i = 0; i < sd.length; i++) {  
    226.             Document doc = searcher.doc(sd[i].doc);  
    227.             String temp=doc.get("name");  
    228.             //做高亮处理  
    229.             TokenStream ts = analyzer.tokenStream("name"new StringReader(temp));  
    230.                
    231.             SerachResult record=new SerachResult();  
    232.             String name = highlighter.getBestFragment(ts,temp);   
    233.             String skydirverName=doc.get("skydirverName");  
    234.             String username=doc.get("username");  
    235.             String shareTime=doc.get("shareTime");  
    236.             String describ=doc.get("describ");  
    237.             String typeId=doc.get("typeId");  
    238.             String id=doc.get("id");  
    239.             String url=doc.get("url");  
    240.                
    241.             record.setName(name);  
    242.             record.setSkydriverName(skydirverName);  
    243.             record.setUsername(username);  
    244.             record.setShareTime(DateFormater.getFormatDate(shareTime,"yyyy-MM-dd HH:mm:ss"));  
    245.             record.setDescrib(describ);  
    246.             record.setTypeId(Integer.parseInt(typeId));  
    247.             record.setId(new BigInteger(id));  
    248.             record.setUrl(url);  
    249.             list.add(record);  
    250.                
    251.             /*System.out.println("name:"+name); 
    252.             System.out.println("skydirverName:"+skydirverName); 
    253.             System.out.println("username:"+username); 
    254.             System.out.println("shareTime:"+shareTime); 
    255.             System.out.println("describ:"+describ); 
    256.             System.out.println("typeId:"+typeId); 
    257.             System.out.println("id:"+id); 
    258.             System.out.println("url:"+url);*/  
    259.         }  
    260.         map.put("source",list);  
    261.         return map;  
    262.     }  
    263.        
    264.     /** 
    265.      * 根据前缀查询 
    266.      * @Author haoning 
    267.      */  
    268.     public void prefixSearch(String filedStr,String queryStr) throws Exception{  
    269.         File indexDir = new File(DISC_URL);    
    270.         //索引目录    
    271.         Directory dir=FSDirectory.open(indexDir);    
    272.         //根据索引目录创建读索引对象    
    273.         IndexReader reader = IndexReader.open(dir);    
    274.         //搜索对象创建    
    275.         IndexSearcher searcher = new IndexSearcher(reader);  
    276.            
    277.         Term term = new Term(filedStr, queryStr);  
    278.         Query query = new PrefixQuery(term);  
    279.            
    280.         ScoreDoc[] docs = searcher.search(query, 3).scoreDocs;  
    281.         printScoreDoc(docs, searcher);  
    282.     }  
    283.        
    284.     /** 
    285.      * 通配符查询 
    286.      * @Author haoning 
    287.      */  
    288.     public void wildcardSearch(String filedStr,String queryStr) throws Exception{  
    289.         File indexDir = new File(DISC_URL);    
    290.         //索引目录    
    291.         Directory dir=FSDirectory.open(indexDir);    
    292.         //根据索引目录创建读索引对象    
    293.         IndexReader reader = IndexReader.open(dir);    
    294.         //搜索对象创建    
    295.         IndexSearcher searcher = new IndexSearcher(reader);  
    296.            
    297.         Term term = new Term(filedStr, queryStr);  
    298.         Query query = new WildcardQuery(term);  
    299.         ScoreDoc[] docs = searcher.search(query, 3).scoreDocs;  
    300.         printScoreDoc(docs, searcher);  
    301.     }  
    302.        
    303.     /** 
    304.      * 分词查询 
    305.      * @Author haoning 
    306.      */  
    307.     public void analyzerSearch(String filedStr,String queryStr) throws Exception{  
    308.         File indexDir = new File(DISC_URL);    
    309.         //索引目录    
    310.         Directory dir=FSDirectory.open(indexDir);    
    311.         //根据索引目录创建读索引对象    
    312.         IndexReader reader = IndexReader.open(dir);    
    313.         //搜索对象创建    
    314.         IndexSearcher searcher = new IndexSearcher(reader);  
    315.            
    316.         QueryParser queryParser = new QueryParser(version, filedStr, analyzer);  
    317.         Query query = queryParser.parse(queryStr);  
    318.            
    319.         ScoreDoc[] docs = searcher.search(query, 3).scoreDocs;  
    320.         printScoreDoc(docs, searcher);  
    321.     }  
    322.        
    323.     /** 
    324.      * 多属性分词查询 
    325.      * @Author haoning 
    326.      */  
    327.     public void multiAnalyzerSearch(String[] filedStr,String queryStr) throws Exception{  
    328.         File indexDir = new File(DISC_URL);    
    329.         //索引目录    
    330.         Directory dir=FSDirectory.open(indexDir);    
    331.         //根据索引目录创建读索引对象    
    332.         IndexReader reader = IndexReader.open(dir);    
    333.         //搜索对象创建    
    334.         IndexSearcher searcher = new IndexSearcher(reader);  
    335.         QueryParser queryParser = new MultiFieldQueryParser(version, filedStr, analyzer);  
    336.         Query query = queryParser.parse(queryStr);  
    337.            
    338.         ScoreDoc[] docs = searcher.search(query, 3).scoreDocs;  
    339.         printScoreDoc(docs, searcher);  
    340.     }  
    341.        
    342.     public void printScoreDoc(ScoreDoc[] docs,IndexSearcher searcher)throws Exception{  
    343.         for (int i = 0; i < docs.length; i++) {  
    344.             List<Fieldable> list = searcher.doc(docs[i].doc).getFields();  
    345.             for (Fieldable fieldable : list) {  
    346.                 String fieldName = fieldable.name();  
    347.                 String fieldValue = fieldable.stringValue();  
    348.                 System.out.println(fieldName+" : "+fieldValue);  
    349.             }  
    350.         }  
    351.     }  
    352. }  

    注意由于去转盘网(http://www.quzhuanpan.com)是部署到linux上的,所以DISC_URL可以更具系统变换,我是通过url来判定索引文件是否唯一的,你可以更具id来判断,具体情况具体对待吧。

    下面是索引部分:

    [java]  view plain  copy
    1. package com.tray.indexData;  
    2.    
    3. import java.sql.SQLException;  
    4. import org.apache.lucene.document.Document;  
    5. import org.apache.lucene.document.Field;  
    6. import com.mysql.jdbc.Connection;  
    7. import com.mysql.jdbc.ResultSet;  
    8. import com.mysql.jdbc.Statement;  
    9.    
    10. public class IndexFile {  
    11.        
    12.      private static Connection conn = null;       
    13.      private static Statement stmt = null;    
    14.      private final int NUM=500000;  
    15.      private LuceneSearch ls;  
    16.      private long count=0;  
    17.         
    18.      public ResultSet deal6SourceTable(String tableName) throws SQLException{  
    19.            String sql = "SELECT distinct `NAME`,SKYDRIVER_NAME,USERNAME,SHARE_TIME,DESCRIB,TYPE_ID,ID,URL FROM "+tableName+" where STATUS=1 and TYPE_ID !='-1' and (TYPE_NAME is null or TYPE_NAME!=1) limit "+NUM;  
    20.            //System.out.println(sql);  
    21.            ResultSet rs = (ResultSet) stmt.executeQuery(sql);  
    22.            return rs;  
    23.      }  
    24.         
    25.      public void update6SourceTable(String tableName) throws SQLException{  
    26.            Statement st = (Statement) conn.createStatement();  
    27.            String sql = "update "+tableName+" set TYPE_NAME=1 where STATUS=1 and TYPE_ID !='-1' and (TYPE_NAME is null or TYPE_NAME!=1) limit "+NUM;  
    28.            //System.out.println("update"+sql);  
    29.             try {  
    30.                 st.executeUpdate(sql);  
    31.             } catch (SQLException e) {  
    32.                 e.printStackTrace();  
    33.             }  
    34.      }  
    35.         
    36.      public void indexInit(){//数据库+lcene初始化  
    37.         conn = (Connection) JdbcUtil.getConnection();       
    38.         if(conn == null) {       
    39.             try {  
    40.                 throw new Exception("数据库连接失败!");  
    41.             } catch (Exception e) {  
    42.                 e.printStackTrace();  
    43.             }       
    44.         }  
    45.         ls=new LuceneSearch();  
    46.         try {  
    47.             ls.init();  
    48.         } catch (Exception e2) {  
    49.             e2.printStackTrace();  
    50.         }  
    51.      }  
    52.         
    53.      public void indexEnd(){//数据库+lcene关闭  
    54.             
    55.          ls.closeWriter();  
    56.          try {  
    57.                 conn.close();//关闭数据库  
    58.              } catch (SQLException e) {  
    59.                 e.printStackTrace();  
    60.           }  
    61.      }  
    62.         
    63.      public void Index6Data() throws SQLException{     
    64.             try {  
    65.                 stmt = (Statement) conn.createStatement();  
    66.             } catch (SQLException e1) {  
    67.                 e1.printStackTrace();  
    68.             }  
    69.                
    70.             ResultSet r1=null;  
    71.             ResultSet r2=null;  
    72.             ResultSet r3=null;  
    73.             ResultSet r4=null;  
    74.             ResultSet r5=null;  
    75.             ResultSet r6=null;  
    76.                
    77.             boolean stop=false;  
    78.             do{  
    79.                  r1=deal6SourceTable("film_and_tv_info");  
    80.                  stop=this.createIndex(r1,ls,"1");   //给数据库创建索引,此处执行一次,不要每次运行都创建索引,以后数据有更新可以后台调用更新索引   
    81.                  if(!stop){  
    82.                      ls.commit();//加个判断条件  
    83.                  }  
    84.                  //System.out.println("stop"+stop);  
    85.                    
    86.             }while(!stop);  
    87.               
    88.             stop=false;  
    89.             do{  
    90.                  r2=deal6SourceTable("music_and_mv_info");  
    91.                  stop=this.createIndex(r2,ls,"2");   //给数据库创建索引,此处执行一次,不要每次运行都创建索引,以后数据有更新可以后台调用更新索引    
    92.                  if(!stop){  
    93.                      ls.commit();//加个判断条件  
    94.                  }  
    95.                    
    96.             }while(!stop);  
    97.                
    98.             stop=false;  
    99.             do{  
    100.                  r3=deal6SourceTable("e_book_info");  
    101.                  stop=this.createIndex(r3,ls,"3");   //给数据库创建索引,此处执行一次,不要每次运行都创建索引,以后数据有更新可以后台调用更新索引    
    102.                  if(!stop){  
    103.                      ls.commit();//加个判断条件  
    104.                  }  
    105.                    
    106.             }while(!stop);  
    107.                
    108.             stop=false;  
    109.             do{  
    110.                  r4=deal6SourceTable("bt_file_info");  
    111.                  stop=this.createIndex(r4,ls,"4");   //给数据库创建索引,此处执行一次,不要每次运行都创建索引,以后数据有更新可以后台调用更新索引    
    112.                  if(!stop){  
    113.                      ls.commit();//加个判断条件  
    114.                  }  
    115.                    
    116.             }while(!stop);  
    117.                
    118.             stop=false;  
    119.             do{  
    120.                  r5=deal6SourceTable("characteristic_software_info");  
    121.                  stop=this.createIndex(r5,ls,"5");   //给数据库创建索引,此处执行一次,不要每次运行都创建索引,以后数据有更新可以后台调用更新索引    
    122.                  if(!stop){  
    123.                      ls.commit();//加个判断条件  
    124.                  }  
    125.                    
    126.             }while(!stop);  
    127.                
    128.             stop=false;  
    129.             do{  
    130.                  r6=deal6SourceTable("source_code_info");  
    131.                  stop=this.createIndex(r6,ls,"6");   //给数据库创建索引,此处执行一次,不要每次运行都创建索引,以后数据有更新可以后台调用更新索引    
    132.                  if(!stop){  
    133.                      ls.commit();//加个判断条件  
    134.                  }  
    135.                    
    136.             }while(!stop);  
    137.             stop=false;  
    138.               
    139.      }  
    140.         
    141.      public ResultSet deal2Share(String tableName) throws SQLException{  
    142.         String sql = "SELECT  distinct NAME,SKYDRIVER_NAME,USERNAME,SHARE_TIME,DESCRIB,TYPE_ID,ID,SHORTURL from "+tableName+" where STATUS=1  and FS_ID ='1' limit "+NUM; //利用FS_ID这个字段,没什么用处   
    143.         ResultSet rs = (ResultSet) stmt.executeQuery(sql);  
    144.         return rs;  
    145.     }  
    146.        
    147.     public ResultSet deal3Share(String tableName) throws SQLException{  
    148.         String sql = "SELECT  distinct title,channel,uid,ctime,description,port,id,shorturl from "+tableName+" where name ='1' limit "+NUM;    
    149.         ResultSet rs = (ResultSet) stmt.executeQuery(sql);  
    150.         return rs;  
    151.     }  
    152.        
    153.     public void Index3Data() throws SQLException{  
    154.             try {  
    155.                 stmt = (Statement) conn.createStatement();  
    156.             } catch (SQLException e1) {  
    157.                 e1.printStackTrace();  
    158.             }  
    159.                
    160.             ResultSet r1=null;  
    161.             ResultSet r2=null;  
    162.             ResultSet r3=null;  
    163.                
    164.             boolean stop=false;  
    165.             do{  
    166.                  r1=deal2Share("share1");  
    167.                  stop=this.createIndex(r1,ls,"7");   //给数据库创建索引,此处执行一次,不要每次运行都创建索引,以后数据有更新可以后台调用更新索引    
    168.                  if(!stop){  
    169.                      ls.commit();//加个判断条件  
    170.                  }  
    171.                  //System.out.println("stop"+stop);  
    172.                    
    173.             }while(!stop);  
    174.               
    175.             stop=false;  
    176.             do{  
    177.                  r2=deal2Share("share2");  
    178.                  stop=this.createIndex(r2,ls,"8");   //给数据库创建索引,此处执行一次,不要每次运行都创建索引,以后数据有更新可以后台调用更新索引    
    179.                  if(!stop){  
    180.                      ls.commit();//加个判断条件  
    181.                  }  
    182.                    
    183.             }while(!stop);  
    184.                
    185.             stop=false;  
    186.             do{  
    187.                  r3=deal3Share("share3");  
    188.                  stop=this.createIndex(r3,ls,"9");   //给数据库创建索引,此处执行一次,不要每次运行都创建索引,以后数据有更新可以后台调用更新索引    
    189.                  if(!stop){  
    190.                      ls.commit();//加个判断条件  
    191.                  }  
    192.                    
    193.             }while(!stop);  
    194.             stop=false;  
    195.         }  
    196.        
    197.         public void update2ShareTable(String tableName) throws SQLException{  
    198.             Statement st = (Statement) conn.createStatement();  
    199.            String sql = "update "+tableName+" set FS_ID=0 where STATUS=1  and FS_ID ='1' limit "+NUM; //利用FS_ID这个字段,没什么用处   
    200.            //System.out.println("update"+sql);  
    201.             try {  
    202.                 st.executeUpdate(sql);  
    203.             } catch (SQLException e) {  
    204.                 e.printStackTrace();  
    205.             }  
    206.         }  
    207.            
    208.         public void update3ShareTable(String tableName) throws SQLException{  
    209.             Statement st = (Statement) conn.createStatement();  
    210.            String sql = "update "+tableName+" set name=0 where name ='1' limit "+NUM;    
    211.            //System.out.println("update"+sql);  
    212.             try {  
    213.                 st.executeUpdate(sql);  
    214.             } catch (SQLException e) {  
    215.                 e.printStackTrace();  
    216.             }  
    217.         }  
    218.               
    219.         public boolean createIndex(ResultSet rs,LuceneSearch ls,String mark) {  
    220.             try {  
    221.                 String tableName=null;  
    222.                 if(mark.equals("1")){  
    223.                     tableName="film_and_tv_info";  
    224.                 }  
    225.                 if(mark.equals("2")){  
    226.                     tableName="music_and_mv_info";  
    227.                 }  
    228.                 if(mark.equals("3")){  
    229.                     tableName="e_book_info";  
    230.                 }  
    231.                 if(mark.equals("4")){  
    232.                     tableName="bt_file_info";  
    233.                 }  
    234.                 if(mark.equals("5")){  
    235.                     tableName="characteristic_software_info";  
    236.                 }  
    237.                 if(mark.equals("6")){  
    238.                     tableName="source_code_info";  
    239.                 }  
    240.                 if(mark.equals("7")){  
    241.                     tableName="share1";  
    242.                 }  
    243.                 if(mark.equals("8")){  
    244.                     tableName="share2";  
    245.                 }  
    246.                 if(mark.equals("9")){  
    247.                     tableName="share3";  
    248.                 }  
    249.    
    250.                 boolean isNull=rs.next();  
    251.                 //System.out.println("hehe"+isNull);  
    252.                 if(isNull==false){  
    253.                     return true;//处理完毕  
    254.                 }  
    255.                 while(isNull){  
    256.                     if(Integer.parseInt(mark)>=1&&Integer.parseInt(mark)<=8){  
    257.                         Document doc = new Document();    
    258.                         //System.out.println("name"+rs.getString("NAME"));          
    259.                         Field name = new Field("name",rs.getString("NAME"),Field.Store.YES,Field.Index.ANALYZED);  
    260.                         String skName=rs.getString("SKYDRIVER_NAME");  
    261.                         if(skName==null){  
    262.                             skName="百度";  
    263.                         }  
    264.                         Field skydirverName = new Field("skydirverName",skName, Field.Store.YES,Field.Index.NOT_ANALYZED);  
    265.                         Field username = new Field("username",rs.getString("USERNAME"),Field.Store.YES, Field.Index.ANALYZED);      
    266.                         Field shareTime = new Field("shareTime",rs.getString("SHARE_TIME"), Field.Store.YES,Field.Index.NOT_ANALYZED);  
    267.                         String desb=rs.getString("DESCRIB");  
    268.                         if(desb==null){  
    269.                             desb="-1";  
    270.                         }  
    271.                         Field describ = new Field("describ",desb,Field.Store.NO,Field.Index.NOT_ANALYZED);       
    272.                         Field typeId = new Field("typeId",rs.getString("TYPE_ID"), Field.Store.YES,Field.Index.NOT_ANALYZED);   
    273.                         Field id = new Field("id",rs.getString("ID"),Field.Store.YES,Field.Index.NOT_ANALYZED);  
    274.                         Field url =null;  
    275.                         if(Integer.parseInt(mark)>=7&&Integer.parseInt(mark)<=8){  
    276.                             url = new Field("url",rs.getString("SHORTURL"), Field.Store.YES,Field.Index.ANALYZED);   
    277.                         }  
    278.                         else{  
    279.                             url = new Field("url",rs.getString("URL"), Field.Store.YES,Field.Index.ANALYZED);    
    280.                         }  
    281.                         doc.add(name);  
    282.                         doc.add(skydirverName);  
    283.                         doc.add(username);  
    284.                         doc.add(shareTime);  
    285.                         doc.add(describ);  
    286.                         doc.add(typeId);  
    287.                         doc.add(id);  
    288.                         doc.add(url);  
    289.                         ls.singleUpdate(doc);//用跟新更为合适       
    290.                         isNull=rs.next();  
    291.                     }  
    292.                     else{  
    293.                         Document doc = new Document();    
    294.                         //System.out.println("title"+rs.getString("title"));          
    295.                         Field name = new Field("name",rs.getString("title"),Field.Store.YES,Field.Index.ANALYZED);  
    296.                         String skName=rs.getString("channel");  
    297.                         Field skydirverName = new Field("skydirverName",skName, Field.Store.YES,Field.Index.NOT_ANALYZED);  
    298.                         Field username = new Field("username",rs.getString("uid"),Field.Store.YES, Field.Index.ANALYZED);       
    299.                         Field shareTime = new Field("shareTime",rs.getString("ctime"), Field.Store.YES,Field.Index.NOT_ANALYZED);  
    300.                         String desb=rs.getString("description");  
    301.                         if(desb==null){  
    302.                             desb="-1";  
    303.                         }  
    304.                         Field describ = new Field("describ",desb,Field.Store.NO,Field.Index.NOT_ANALYZED);       
    305.                         Field typeId = new Field("typeId",rs.getString("port"), Field.Store.YES,Field.Index.NOT_ANALYZED);  
    306.                         Field id = new Field("id",rs.getString("id"),Field.Store.YES,Field.Index.NOT_ANALYZED);      
    307.                         Field url = new Field("url",rs.getString("shorturl"), Field.Store.YES,Field.Index.ANALYZED);    
    308.                            
    309.                         doc.add(name);  
    310.                         doc.add(skydirverName);  
    311.                         doc.add(username);  
    312.                         doc.add(shareTime);  
    313.                         doc.add(describ);  
    314.                         doc.add(typeId);  
    315.                         doc.add(id);  
    316.                         doc.add(url);  
    317.                         ls.singleUpdate(doc);//用跟新更为合适       
    318.                         isNull=rs.next();  
    319.                     }  
    320.                     count=count+1;  
    321.                 }  
    322.                 if(Integer.parseInt(mark)>=1&&Integer.parseInt(mark)<=6){  
    323.                     update6SourceTable(tableName);//处理完成后做标志  
    324.                 }  
    325.                 else if(Integer.parseInt(mark)>=7&&Integer.parseInt(mark)<=8){  
    326.                     update2ShareTable(tableName);//处理完成后做标志  
    327.                 }  
    328.                 else{  
    329.                     update3ShareTable(tableName);//处理完成后做标志  
    330.                 }  
    331.                 System.out.println("Has index "+count+"条数据,数据来自表"+tableName);  
    332.                    
    333.             } catch (Exception e) {  
    334.                 e.printStackTrace();  
    335.             }  
    336.             return false;  
    337.         }  
    338. }  

    数据库之类的请不要关心,看思路即可,你如果需要换成你的即可,这里就不多说了。看最后的部分:

    [java]  view plain  copy
    1. package com.tray.indexData;  
    2.    
    3. import java.sql.SQLException;  
    4.    
    5.    
    6.    
    7. public class Application {  
    8.        
    9.     public static void main(String[] args){  
    10.         /*IndexFile indexFile=new IndexFile(); 
    11.         indexFile.indexInit(); 
    12.         try { 
    13.             indexFile.Index6Data(); 
    14.         } catch (SQLException e1) { 
    15.             e1.printStackTrace(); 
    16.         } 
    17.         indexFile.indexEnd();*/  
    18.            
    19.         IndexFile indexFile1=new IndexFile();  
    20.         indexFile1.indexInit();  
    21.         try {  
    22.             indexFile1.Index3Data();  
    23.         } catch (SQLException e1) {  
    24.             e1.printStackTrace();  
    25.         }  
    26.         indexFile1.indexEnd();  
    27.            
    28.         LuceneSearch lch=new LuceneSearch();  
    29.         try {  
    30.             long a = System.currentTimeMillis();  
    31.             lch.highLightSearch("name""flv"1,3);  
    32.             long b = System.currentTimeMillis();  
    33.             long c = b - a;  
    34.             System.out.println("[高级检索花费时间:" + c + "毫秒]");  
    35.         } catch (Exception e) {  
    36.             e.printStackTrace();  
    37.         }  
    38.     }  
    39. }  
    展开全文
  • 采用正向和反向最大匹配算法,可拆分文件,字符串等,也可扩展自己想要的功能,很方便
  • //Java实现逆向最大匹配中文分词算法public class SplitChineseCharacter { public static void main(String[] args) { String input = "太好了,今天是星期六啊"; // 要匹配的字符串 new Split(input)....
    写道
    //Java实现逆向最大匹配中文分词算法
    public class SplitChineseCharacter {
    public static void main(String[] args) {
    String input = "太好了,今天是星期六啊"; // 要匹配的字符串
    new Split(input).start();
    }
    }

    class Split {
    private String[] dictionary = {"今天","是","星期","星期六"}; //词典
    private String input = null;

    public Split(String input) {
    this.input = input;
    }

    public void start() {
    String temp = null;
    for(int i=0;i<this.input.length();i++) {
    temp = this.input.substring(i); // 每次从字符串的首部截取一个字,并存到temp中
    // System.out.println("*****" + temp + "*********" + this.input);
    // 如果该词在字典中, 则删除该词并在原始字符串中截取该词
    if(this.isInDictionary(temp)) {
    System.out.println(temp);
    this.input = this.input.replace(temp, "");
    i = -1; // i=-1是因为要重新查找, 而要先执行循环中的i++
    }
    }

    // 当前循环完毕,词的末尾截去一个字,继续循环, 直到词变为空
    if(null != this.input && !"".equals(this.input)) {
    this.input = this.input.substring(0,this.input.length()-1);
    this.start();
    }
    }

    //判断当前词是否在字典中
    public boolean isInDictionary(String temp) {
    for(int i=0;i<this.dictionary.length;i++) {
    if(temp.equals(this.dictionary[i])) {
    return true;
    }
    }
    return false;
    }
    }

    /**
    过程分析:
    第一词循环:
    太好了,今天是星期六啊
    好了,今天是星期六啊
    了,今天是星期六啊
    ,今天是星期六啊
    今天是星期六啊
    天是星期六啊
    是星期六啊
    星期六啊
    期六啊
    六啊

    第一次循环没有找到,则从“太好了,今天是星期六啊”中把最后一个截取,开始第二次循环

    第二次循环:
    太好了,今天是星期六
    好了,今天是星期六
    了,今天是星期六
    ,今天是星期六
    今天是星期六
    天是星期六
    是星期六
    星期六 --------->输出:星期六,并在原字符串中截去“星期六”-->变为“太好了,今天是”
    太好了,今天是
    好了,今天是
    了,今天是
    ,今天是
    今天是
    天是
    是 ----------> 输出:是, 并在原字符串中截去“是”-->变为“太好了,今天”
    直到原字符串变为空。
    */

     

    展开全文
  • 前向分词最大匹配算法理论介绍前向最大匹配算法具体代码实现分词结果 理论介绍 分词是自然语言处理的一个基本工作,中文分词和英文不同,字词之间没有空格。中文分词是文本挖掘的基础,对于输入的一段中文,成功的...

    理论介绍

    分词是自然语言处理的一个基本工作,中文分词和英文不同,字词之间没有空格。中文分词是文本挖掘的基础,对于输入的一段中文,成功的进行中文分词,可以达到电脑自动识别语句含义的效果。中文分词技术属于自然语言处理技术范畴,对于一句话,人可以通过自己的知识来明白哪些是词,哪些不是词,但如何让计算机也能理解?其处理过程就是分词算法。

    可以将中文分词方法简单归纳为:

    1. 基于词表的分词方法
    2. 基于统计的分词方法
    3. 基于序列标记的分词方法

    其中,基于词表的分词方法最为简单,根据起始匹配位置不同可以分为:

    1. 前向最大匹配算法
    2. 后向最大匹配算法
    3. 双向最大匹配算法

    三种方法思想都很简单,今天就用python实现前向最大匹配算法

    word分词是一个Java实现的分布式的中文分词组件,提供了多种基于词典的分词算法,并利用ngram模型来消除歧义。能准确识别英文、数字,以及日期、时间等数量词,能识别人名、地名、组织机构名等未登录词。能通过自定义配置文件来改变组件行为,能自定义用户词库、自动检测词库变化、支持大规模分布式环境,能灵活指定多种分词算

    展开全文
  • 这篇将使用Java实现基于规则的中文分词算法,一个中文词典将实现准确率高达85%的分词结果。使用经典算法:正向最大匹配和反向最大匹配算法,然后双剑合璧,双向最大匹配。

    目录

    前言

    一、中文分词理论描述

    二、算法描述

    1、正向最大匹配算法

    2、反向最大匹配算法

    3、双剑合璧

    三、案例描述

    四、JAVA实现完整代码

    五、组装UI

    六、总结


    前言

    这篇将使用Java实现基于规则的中文分词算法,一个中文词典将实现准确率高达85%的分词结果。使用经典算法:正向最大匹配和反向最大匹配算法,然后双剑合璧,双向最大匹配。

    一、中文分词理论描述

    根据相关资料,中文分词概念的理论描述,我总结如下:

    中文分词是将一个汉字序列切分成一个一个单独的词,将连续的字序列按照一定的规范重新组合成词序列的过程,把字与字连在一起的汉语句子分成若干个相互独立、完整、正确的单词,词是最小的、能独立活动的、有意义的语言成分。

    中文分词应用广泛,是文本挖掘的基础,在中文文本处理中意义重大,对于输入的一段中文,成功的进行中文分词,可以达到电脑自动识别语句含义的效果。目前,常用流行的以及分次效果好的工具库包括:jieba、HanLP、LTP、FudanNLP等。

    我们知道,调用工具方便容易,但是如果自己实现写一个算法实现,那不是更加有成就感^_^。

    接下来将一步步介绍最容易理解,最简单,效果还很不错的中文分词算法,据说准确率能达到85%!!

    二、算法描述

    1、正向最大匹配算法

    所谓正向,就是从文本串左边正向扫描,取出子串与词典进行匹配。

    算法我分为两步来理解:

    假设初始化取最大匹配长度为MaxLen,当前位置pos=0,处理结果result=””,每次取词str,取词长度len,待处理串segstr。

    1. len=MaxLen,取字符串0到len的子串,查找词典,若匹配到则赋值str,加到result,在保证pos+len<=segstr.length()情况下,pos=pos+len,向后匹配,直到字符串扫描完成,结束算法。
    2. 若词典未找到,若len>1,减小匹配长度同时len=MaxLen-1,执行步骤(1),否则,取出剩余子串,执行步骤(1)。

    算法代码如下:

        public void MM(String str, int len, int frompos) {
            if (frompos + 1 > str.length())
                return;
            String curstr = "";
            //此处可以设置断点
            int llen = str.length() - frompos;
            if (llen <= len)//句末边界处理
                curstr = str.substring(frompos, frompos + llen);//substring获取的子串是下标frompos~frompos+llen-1
            else
                curstr = str.substring(frompos, frompos + len);
    
            if (dict.containsKey(curstr)) {
                result = result + curstr + "/ ";
                Len = MaxLen;
                indexpos = frompos + len;
                MM(str, Len, indexpos);
            } else {
                if (Len > 1) {
                    Len = Len - 1;
                } else {
                    result = result + str + "/ ";
                    frompos = frompos + 1;
                    Len = MaxLen;
                }
                MM(str, Len, frompos);
            }
        }

     从算法代码看出,很容易理解,细节部分在于边界处理。

    测试一下,我输入文本,"我爱自然语言处理,赞赏评论收藏我的文章是我的动力!赶紧关注!"

    分词结果:

    2、反向最大匹配算法

    反向,则与正向相反,从文本串末向左进行扫描。

    假设初始化取最大匹配长度为MaxLen,当前位置pos为字符串尾部,处理结果result=””,每次取词str,取词长度len,待处理串segstr。

    1. len=MaxLen,取字符串pos-len到pos的子串,查找词典,若匹配到则赋值str,加到result,同时pos=pos-len,保证pos-len>=0,向前移动匹配,直到字符串扫描完成,结束算法。
    2. 若词典未找到,若len>1,减小匹配长度同时len=MaxLen-1,执行步骤(1),否则,取出剩余子串,执行步骤(1)。

    算法逻辑类似,取相反方向处理。

    public void RMM(String str, int len, int frompos) {
            if (frompos < 0)
                return;
            String curstr = "";
            //此处可以设置断点
            if (frompos - len + 1 >= 0)//句末边界处理
                curstr = str.substring(frompos - len + 1, frompos + 1);//substring获取的子串是下标frompos~frompos+llen-1
            else
                curstr = str.substring(0, frompos + 1);//到达句首
    
            if (dict.containsKey(curstr)) {
                RmmResult = curstr + "/ " + RmmResult;
                Len = MaxLen;
                indexpos = frompos - len;
                RMM(str, Len, indexpos);
            } else {
                if (Len > 1) {
                    Len = Len - 1;
                } else {
                    RmmResult = RmmResult + str + "/ ";
                    frompos = frompos - 1;
                    Len = MaxLen;
                }
                RMM(str, Len, frompos);
            }
        }

     同样,细节部分在于边界处理,其他基本相同。

    3、双剑合璧

    这里所说的是正向与反向结合,实现双向最大匹配。

    双向最大匹配算法,基于正向、反向最大匹配,对分词结果进一步处理,比较两个结果,做的工作就是遵循某些原则和经验,筛选出两者中更确切地分词结果。原则如下:

    • 多数情况下,反向最大匹配效果更好,若分词结果相同,则返回RMM结果;
    • 遵循切分最少词原则,更大匹配词为更好地分词结果,比较之后返回最少词的切分结果;
    • 根据切分后词长度的大小,选择词长度大者为最终结果。

    具体也需要看开始给定的最大匹配长度为多少。以下代码只实现了原则(1)、(2)。

        public String BMM() throws IOException {
            String Mr = MM_Seg();
            String RMr = RMM_Seg();
            if (Mr.equals(RMr)) {
                return "双向匹配相同,结果为:" + Mr;
            } else {
                List<String> MStr;
                List<String> RStr;
                MStr = Arrays.asList(Mr.trim().split("/"));
                RStr = Arrays.asList(RMr.trim().split("/"));
    
                if (MStr.size() >= RStr.size()) {//多数情况下,反向匹配正确率更高
                    return "双向匹配不同,最佳结果为:" + RMr;
                } else
                    return "双向匹配不同,最佳结果为:" + Mr;
            }
        }

    另外,这与使用的词典大小有关,是否包含常用词。

    三、案例描述

    如果上面还不能完全理解,下面的例子可以更好的理解算法执行过程。

    正向最大匹配算法:

    取MaxLen=3,SegStr=”对外经济技术合作与交流不断扩大”,maxNum=3,len=3,result=””,pos=0,curstr=””.

    第一次,curstr=”对外经”,查找词典,未找到,将len-1,得到curstr=”对外”,此时匹配到词典,将结果加入result=”对外/ ”.pos=pos+len.

    第二次,curstr=”经济技”,查找词典,未找到,将len-1,得到curstr=”经济”,此时匹配到词典,将结果加入result=”对外/ 经济/ ”.pos=pos+len.

    以此类推...

    最后一次,边界,pos=13,因为只剩下”扩大”两个字,所以取出全部,查找词典并匹配到,将结果加入result=”对外/ 经济/ 技术/ 合作/ 与/ 交流/ 不断/ 扩大/ ”.此时pos+1>SegStr.length(),结束算法。 


    反向最大匹配算法:

    取MaxLen=3,SegStr=”对外经济技术合作与交流不断扩大”,maxNum=3,len=3,result=””,pos=14,curstr=””.

    第一次,curstr=”断扩大”,查找词典,未找到,将len-1,得到curstr=”扩大”,此时匹配到词典,将结果加入result=”扩大/ ”.pos=pos-len.

    第二次,MaxLen=3,curstr=”流不断”,查找词典,未找到,将len-1,得到curstr=”不断”,此时匹配到词典,将结果加入result=”不断/ 扩大/ ”.pos=pos-len.

    以此类推...

    最后一次,边界,pos=1,因为只剩下”对外”两个字,所以取出全部,查找词典并匹配到,将结果加入result=”对外/ 经济/ 技术/ 合作/ 与/ 交流/ 不断/ 扩大/ ”.此时pos-1<0,结束算法。

    四、JAVA实现完整代码

     除了分词算法实现,还需要读入词典,对词典进行预处理,具体

    package ex1;
    
    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.*;
    
    
    public class seg {
    
        String result;
        String RmmResult;
        String segstring;
        int MaxLen;
        int Len;
        int indexpos;
        Map<String, String> dict; 
    
        public seg(String inputstr, int maxlen) {//构造函数
            segstring = inputstr;
            MaxLen = maxlen;
            Len = MaxLen;
            indexpos = 0;
            result = "";
            RmmResult = "";
            dict = new HashMap<String, String>();
    
        }
    
        public void ReadDic() throws FileNotFoundException, IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("chineseDic.txt"), "GBK"));
            String line = null;
            while ((line = br.readLine()) != null) {
                String[] words = line.trim().split(",");//词典包含词性标注,需要将词与标注分开,放入列表
                String word = words[0];
                String cx = words[1];
                dict.put(word, cx);
            }
            br.close();
        }
    
        public String MM_Seg() throws IOException {//正向最大匹配算法
            try {
                ReadDic();//读入字典
                MM(segstring, MaxLen, 0);//正向最大分词
                return result;
            } catch (IOException e) {
                return "Read Error!";
            }
        }
    
        public void MM(String str, int len, int frompos) {
            if (frompos + 1 > str.length())
                return;
            String curstr = "";
            //此处可以设置断点
            int llen = str.length() - frompos;
            if (llen <= len)//句末边界处理
                curstr = str.substring(frompos, frompos + llen);//substring获取的子串是下标frompos~frompos+llen-1
            else
                curstr = str.substring(frompos, frompos + len);
    
            if (dict.containsKey(curstr)) {
                result = result + curstr + "/ ";
                Len = MaxLen;
                indexpos = frompos + len;
                MM(str, Len, indexpos);
            } else {
                if (Len > 1) {
                    Len = Len - 1;
                } else {
                    result = result + str + "/ ";
                    frompos = frompos + 1;
                    Len = MaxLen;
                }
                MM(str, Len, frompos);
            }
        }
    
        public String RMM_Seg() throws IOException {//正向最大匹配算法
            try {
                ReadDic();//读入字典
                RMM(segstring, MaxLen, segstring.length() - 1);//正向最大分词
                return RmmResult;
            } catch (IOException e) {
                return "Read Error!";
            }
        }
    
        public void RMM(String str, int len, int frompos) {
            if (frompos < 0)
                return;
            String curstr = "";
            //此处可以设置断点
            if (frompos - len + 1 >= 0)//句末边界处理
                curstr = str.substring(frompos - len + 1, frompos + 1);//substring获取的子串是下标frompos~frompos+llen-1
            else
                curstr = str.substring(0, frompos + 1);//到达句首
    
            if (dict.containsKey(curstr)) {
                RmmResult = curstr + "/ " + RmmResult;
                Len = MaxLen;
                indexpos = frompos - len;
                RMM(str, Len, indexpos);
            } else {
                if (Len > 1) {
                    Len = Len - 1;
                } else {
                    RmmResult = RmmResult + str + "/ ";
                    frompos = frompos - 1;
                    Len = MaxLen;
                }
                RMM(str, Len, frompos);
            }
        }
    
        public String BMM() throws IOException {
            String Mr = MM_Seg();
            String RMr = RMM_Seg();
            if (Mr.equals(RMr)) {
                return "双向匹配相同,结果为:" + Mr;
            } else {
                List<String> MStr;
                List<String> RStr;
                MStr = Arrays.asList(Mr.trim().split("/"));
                RStr = Arrays.asList(RMr.trim().split("/"));
    
                if (MStr.size() >= RStr.size()) {//多数情况下,反向匹配正确率更高
                    return "双向匹配不同,最佳结果为:" + RMr;
                } else
                    return "双向匹配不同,最佳结果为:" + Mr;
            }
        }
    
        public String getResult() {
            return result;
        }
    
        public static void main(String[] args) throws IOException, Exception {
            seg s = new seg("我爱自然语言处理,赞赏评论收藏我的文章是我的动力!赶紧关注!", 3);
    //        String result = s.MM_Seg();
            String result = s.RMM_Seg();
            System.out.println(result);
    
        }
    }

    五、组装UI

    我是用的开发软件为是IDEA,一个方便之处可以拖动组件组装UI界面。也可以自行写JavaFX实现简单布局。

    这是简单页面的设计:

    UI界面可以有更好的用户体验,通过UI界面的元素调用方法,减少每次测试运行算法脚本的繁琐。

    实验演示:

    每次可以观察不同最大匹配长度分词后的结果。

    "年中"词语解析:

    在词典中,是这样的,可以发现满足最大匹配。

    双向最大匹配算法,结果提示:

    六、总结

    这篇介绍了使用Java实现基于规则的中文分词算法,使用经典算法:正向最大匹配和反向最大匹配算法,然后双剑合璧,双向最大匹配。最后设计简单UI界面,实现稍微高效的中文分词处理,结果返回。

    1. 双向最大匹配算法原则,希望句子最长词保留完整、最短词数量最少、单字词问题,目前只解决了句子切分最少词问题。
    2. 正向反向匹配算法可以进一步优化结构,提高执行效率,目前平均耗时20ms。
    3. UI界面增加输入输出提示语,方便用户使用,在正确的区域输入内容。
    4. 将最大匹配长度设置为可输入,实现每次可以观察不同MaxLen得到的切分结果。
    5. 双向最大匹配按钮点击之后,返回结果同时返回MM和RMM结果是否一样的提示,方便查看。


    我的CSDN博客: https://blog.csdn.net/Charzous/article/details/108817914

    展开全文
  • Segmentation.java package cn.strong;   import java.util.HashMap;   public class Segmentation {   private String tem = null; private HashMap mapDic, len;   public Seg...
  • 基于词典的正向最大匹配算法(最长词优先匹配),算法会根据词典文件自动调整最大长度,分词的好坏完全取决于词典。   算法流程图如下:   Java实现代码如下:   /** * 基于词典的正向最大匹配算法 *...
  • 使用jieba、前向最大匹配算法、后向最大匹配算法分词 今天我们开始分词,我整理了王家卫电影里的一些台词,总共有79条,分别出自比较有名的《东邪西毒》、《春光乍泄》、《重庆森林》,这个数据集是这样的。 前向...
  • 下面我们看看基于词典的逆向最大匹配算法的实现,实验表明,对于汉语来说,逆向最大匹配算法比(正向)最大匹配算法更有效,如下代码所示:   public static List&lt;String&gt; segRe...
  • 最大匹配分词算法

    千次阅读 2015-05-06 16:36:49
    我们先看分词算法 目前对中文分词有两个方向,其中一个是利用概率的思想对文章分词。 也就是如果两个字,一起出现的频率很高的话,我们可以假设这两个字是一个词。这里可以用一个公式衡量:M(A,B)=P(AB)/P(A)P(B),...
  • 中文文本相似度匹配算法 simHash 海明距离 IK分词 完整的可运行的示例代码 包含simHash 算法,使用IK 对中文文本进行分词处理
  • java实现双向最大匹配算法

    千次阅读 2018-05-22 16:24:34
    结合正向最大匹配算法和反向最大匹配算法得出的双向最大匹配算法,第一部分是正向,第二部分是反向,然后相比较两种算法,得出最优答案 package Bi_MM; import java.io.BufferedReader; import java.io....
  • 基于逆向匹配的中文分词算法,实验结果 步骤 分析 性能比较
  • 但不管实现如何,目前而言的分词系统绝大多数都是基于中文词典的匹配算法。在这里我想介绍一下中文分词的一个最基础算法:最大匹配算法(Maximum Matching,以下简称MM算法)。MM算法有两种:一种正向最大匹配,一种...
  • 前言大家都知道,英文的分词由于单词间是以空格进行分隔的,所以分词要相对的容易些,而中文就不同了,中文中一个句子的分隔就是以字为单位的了,而所谓的正向最大匹配和逆向最大匹配便是一种分词匹配的方法,这里以...
  • java 实现的中文分词算法(代码)

    热门讨论 2011-04-14 20:10:38
    java 实现的基于FMM BMM算法的,中文分词算法(代码)
  • 中文分词应用很广泛,网上也有很多开源项目,下面这篇文章主要给大家介绍了关于java中文分词之正向最大匹配法的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
  • 中文分词一直都是中文自然...但不管实现如何,目前而言的分词系统绝大多数都是基于中文词典的匹配算法。 在这里我想介绍一下中文分词的一个最基础算法:最大匹配算法(Maximum Matching,以下简称MM算法)。M...
  • 双向最大匹配算法(含完整代码实现,ui界面)正向最大匹配算法,逆向最大匹配算法 一、理论描述 中文分词(Chinese Word Segmentation) 指的是将一个汉字序列切分成一个一个单独的词。分词就是将连续的字序列按照一定...
  • 中文分词算法概述:  1:非基于词典的分词(nlp语义领域)  相当于人工智能领域计算。一般用于机器学习,特定领域等方法,... 这类分词算法比较常见,也比较简单粗暴,比如正向/逆向匹配和ik的最细粒度。例如:
  • 2、每来一次分词构造,就顺着trie树进行分词,这将产生很多种结果,于是就生成了一个DGA,分词的有向无环图,终点是句子的左边或者右边(实际上应该分别以左边和右边为终点来做处理)。 3、利用动态规划,从句子的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,547
精华内容 3,018
关键字:

java分词匹配算法

java 订阅