TSE中关于分词的算法的改写最少切分

今天比较闲,想到以前也看了好多tse的代码,还没有上手改过呢,一时也不知从何入手,后来在书上看到了分词的算法,TSE用的是正向最大匹配,其中貌似有个好玩的算法-----最少切分,捣鼓了一下午,终于把代码弄出来了。

如果有人有兴趣的话,在HzSeg中修改SegmentSentenceMM函数的代码,将s2+=SegmentHzStrMM(dict, s1.substr(0,i));

改成s2+=SegmentHzStr_min_cut(dict, s1.substr(0,i));就OK了。

代码显得还是有些冗余,还是有优化的余地的,有时间再改吧。

 1 string get_res(map<int,map<int,int> > path,    map<int,int>  min_path,string s1,int l){
 2 #undef _debug_hzseg
 3 #ifdef _debug_hzseg
 4     cout<<"s1:"<<s1<<"l"<<l<<endl;
 5     for (int i = 0; i < l; i++) {
 6         cout<<"<!-- ";
 7         for (int j = 0; j < l; j++) {
 8             cout<<path[i][j]<<" ";
 9         }
10         cout<<"-->"<<endl;
11     }
12     for (int i = 0; i < l; i++) {
13         cout<<min_path[i];
14     }
15 #endif
16     int i,j,start,next_start,tmp_min;
17     string res;
18     start=0;
19     while(start<l){
20         tmp_min=min_path[start];
21         for(j=start;j<l-1;j++){
22             if((1==path[start][j])&&tmp_min==path[start][j]+min_path[j+1]){//如果这个是最少切分的话,就记录下来
23                 res=res+s1.substr(start*2,j*2-start*2+2)+SEPARATOR;
24                 start=j+1;
25                 break;
26             }
27         }
28         if ((1==path[start][j])&&j == l-1 ) {
29             res = res + s1.substr(start * 2, j * 2 - start * 2 +2) + SEPARATOR;//说明是最后一个了
30             start=l;
31             break;
32         }
33     }
34 return res;
35 }
36 
37 
38 
39 // 最小切分算法
40 string SegmentHzStr_min_cut (CDict &dict, string s1)
41 {
42     int j;
43     int s1_size=s1.size()/2;
44     string tmp;
45     map<int,map<int,int> > path;
46     map<int,int>  min_path;
47     bool isw;
48 
49     for (int i = 0; i < s1_size; i++) {
50         for (int j = 0; j < s1_size; j++) {
51                 path[i][j] = 0;
52         }
53     }
54 
55     for(int i=0;i<s1_size;i++){
56         for(int j=i;j<s1_size;j++){
57             tmp=s1.substr(i*2,j*2-i*2+2);
58             isw=dict.IsWord(tmp);
59             if(isw)
60                 path[i][j]=1;
61         }
62     }
63     for(int i=0;i<s1_size;i++)
64         path[i][i]=1;//每个单独的字认为是一个词
65 
66     map<int,int> min_cut;
67     min_path[s1_size-1]=1;
68     for(int i=s1_size-2;i>=0;i--){//动态规划做的
69         min_path[i]=10000;
70         for(j=i;j<s1_size-1;j++){
71             if(1==path[i][j]&&(min_path[i]>path[i][j]+min_path[j+1])){
72                     min_path[i]=path[i][j]+min_path[j+1];
73             }
74         }
75         if (path[i][j] ) {
76             min_path[i] = 1;
77         }
78     }
79     string s2=get_res(path,min_path,s1,s1_size);//根据上边算出来的min_path获得最少切分
80     return s2;
81 }
原文地址:https://www.cnblogs.com/kakamilan/p/2623444.html