seq=str.substring(j,num-i);
if(ve.contains(seq)||(num-i-j==1))
{System.out.print(seq+"");
FW.write(seq+"");
j+=num-i-j;
break;
}
}
}
}
}
}
程序说明:
程序由两个类组成,公共类WordSequence和类Sequence,类Sequence主要实现对一个字符串进行分词。
思路是:
首先,把词表中的词存储在一个Vector对象中,这一步很关键。
因为Vector类中提供了一个contains函数可以方便的判断词表中是否有所对照的字符串。
起初,我也尝试了直接用一个字符串数组存储词表中的字符串,但后来发现特别不方便。
然后,根据字符串的长短对其按照正向最大匹配法进行处理。
最后,在main()方法中,定义一个文件字符流,利用readLine()函数没读一行,声明一个Sequence对象,对这行字符串进行处理。
具体程序见上。
5.实验结果及分析
实验结果:
实验分析:
从上述结果可以看出,基本上程序输出的结果是正确的,只有少数词存在一些误差。
而这些误差对于这个算法是完全允许的。
比如“他是研究生物化学的。
”输出结果为“他/是/研究生/物化/学/的/。
”可见,正向最大匹配法并不能做到完美。
有时逆向最大匹配法会比正向最大匹配法四处结果要好很多。
实验二、分词与词性标注系统ICTCLAS
1.实验内容
实验数据:
pku_test.txt未经过分词的文档文件
调用ICTCLAS程序对其中的文档进行分词
2.实验所采用的开发平台及语言工具
开发平台:
ICTCLAS50_Windows_64_JNI、eclipse软件
语言工具:
Java语言
3.系统主要模块流程、源代码
importICTCLAS.I3S.AC.ICTCLAS50;
importjava.util.*;
importjava.io.*;
publicclassWS{
publicstaticvoidmain(String[]args)
{
try
{
ICTCLAS50testICTCLAS50=newICTCLAS50();
//分词所需库的路径
Stringargu=".";
//初始化
if(testICTCLAS50.ICTCLAS_Init(argu.getBytes("GB2312"))==false)
{
System.out.println("InitFail!
");
return;
}
//输入文件名
StringInputfilename="F:
\\pku_test.txt";
byte[]Inputfilenameb=Inputfilename.getBytes();
//分词处理后输出文件名
StringOutputfilename="F:
\\test_result.txt";
byte[]Outputfilenameb=Outputfilename.getBytes();
//文件分词(第一个参数为输入文件的名,第二个参数为文件编码类型,第三个参数为是否标记词性集1yes,0no,第四个参数为输出文件名)
testICTCLAS50.ICTCLAS_FileProcess(Inputfilenameb,2,2,Outputfilenameb);
}catch(Exceptionex)
{
}
}
}
程序说明:
本程序通过调用ICTCLAS系统来实现对字符串分词并加标注。
程序的实现很简单,只是声明一个ICTCLAS50对象并初始化,然后调用其中的ICTCLAS_FileProcess函数即可实现对F:
\\pku_test.txt文件进行分词并加标注。
在调用ICTCLAS系统时普遍说总是编译出错并提示找不到文件。
问题就是出在“Stringargu=".";”,“.”表示出当前目录中查找文件。
虽然可以直接用绝对路径,但初学者常常在这犯错。
最简便的方法就是直接把java源程序的目录设在“C:
\Users\dell\Desktop\ICTCLAS50_Windows_64_JNI\API”。
这样就可以编译通过并输出结果,存储在F:
\\test_result.txt
5.实验结果及分析
实验结果:
(限于篇幅,仅取开头的一段)
共同/d创造/v美好/a的/ude1新/a世纪/n——/wp二/m○/w○/w一年/m新年/t贺词/n
(/wkz二/m○/w○/w○/w年/n十二月/t三十一日/t)/wky(/wkz附/v图片/n1/a张/q)/wky
女士/n们/k,/wd先生/n们/k,/wd同志/n们/k,/wd朋友/n们/k:
/wm
2001年/m新年/t钟声/n即将/d敲响/v。
/wj人类/n社会/n前进/vi的/ude1航船/n就要/d驶入/v21/m世纪/n的/ude1新/a航程/n。
/wj中国/ns人民/n进入/v了/ule向/p现代化/vn建设/vn第三/m步/qv战略/n目标/n迈进/vi的/ude1新/a征程/n。
/wj
在/p这个/rz激动人心/bl的/ude1时刻/n,/wd我/rr很/d高兴/a通过/p中国/ns国际/n广播电台/n、/wn中央人民广播电台/nt和/cc中央电视台/nt,/wd向/p全国/n各族/rz人民/n,/wd向/p香港特别行政区/ns同胞/n、/wn澳门特别行政区/ns同胞/n和/cc台湾/ns同胞/n、/wn海外/s侨胞/n,/wd向/p世界/n各国/rzs的/ude1朋友/n们/k,/wd致以/v新/a世纪/n第一/m个/q新年/t的/ude1祝贺/vn!
/wt
结果分析:
从运行结果可以看出,结果应该是非常准确的。
而且在实际运行时可以发现运行速度特别快。
在实验一中我们编的程序运行完要好几分钟,而这个程序只需不到10秒。
可能其中的算法比较便捷。
实验三、基于语言模型的音字转换
1.实验内容
设计一个基于语言模型的音字转换系统,根据拼音
实验数据:
pku_test_gold.txt经过分词的文档文件
2.实验所采用的开发平台及语言工具
开发平台:
Eclipse软件
语言工具:
Java语言
3.实验的核心思想和算法描述
给定拼音串:
jinjitizhigaige
可能的汉字串:
紧济体质改革
经济体质改革
经济体制改革
使用2-gram计算:
p(CString1)=p(紧)×p(济|紧)×p(体质|济)×p(改革|体质)×
p(CString2)=p(经济)×p(体质|经济)×p(改革|体质)
p(CString3)=p(经济)×p(体制|经济)×p(改革|体制)
比较p(CString1),p(CString2),p(CString3)
4.系统主要模块流程、源代码
importjava.io.*;
importjava.util.Vector;
publicclassWordSequence{
publicstaticvoidmain(Stringargs[]){
try{
Stringpku1="紧济体质改革";
Sequencepku_test1=newSequence(pku1);
Stringpku2="经济体质改革";
Sequencepku_test2=newSequence(pku2);
Stringpku3="经济体制改革";
Sequencepku_test3=newSequence(pku3);
}catch(IOExceptione){
System.out.print(e);
}
}
}
classSequence{
staticfinalintWORD_MAX_LENGTH=9;
doubleT_test=1.00000000;
staticVectorve=newVector();
Stringseq=null;
publicSequence(Stringstr)throwsIOException{
classLoadDictionary{
publicLoadDictionary(FileReaderreader)throwsIOException{
BufferedReaderstream=newBufferedReader(reader);
StringLD=null;
while((LD=stream.readLine())!
=null){ve.add(LD);
}
}
}
FileReaderlist=newFileReader("F:
\\wordlist.txt");
LoadDictionaryDic=newLoadDictionary(list);
intnum=str.length();
Stringfenci[]=newString[6];
intk=0;
if(num<=WORD_MAX_LENGTH){
inti,j=0;
while(jfor(i=0;i+jseq=str.substring(j,num-i);
if(ve.contains(seq)||(num-i-j==1))
{System.out.print(seq+"");
fenci[k]=seq;
k++;
j+=num-i-j;
break;
}
}
}
}
else{inti,j=0;
while(num-j>=WORD_MAX_LENGTH){
i=j+WORD_MAX_LENGTH;
for(;i>j;i--){
seq=str.substring(j,i);
if(ve.contains(seq)||(i-j==1))
{System.out.print(seq+"");
j=i;
break;
}
}
}
while(jfor(i=0;i+jseq=str.substring(j,num-i);
if(ve.contains(seq)||(num-i-j==1))
{System.out.print(seq+"");
j+=num-i-j;
break;
}
}
}
}
FileReaderFder=newFileReader("F:
\\pku_test_gold.txt");
BufferedReaderBR=newBufferedReader(Fder);
StringstrInfo="";
Stringpuk="";
while((puk=BR.readLine())!
=null){strInfo+=puk;}
StringstrSplit="/";
String[]a=dong_split(strInfo,strSplit);
System.out.println(a.length);
intchk=0,cnk=a.length;
for(k=1;k<6;k++){
if(fenci[k]!
=null){
System.out.println("fenci["+k+"]:
"+fenci[k]);
if(k==1){chk=0;
for(intn=0;nif(a[n].equals(fenci[k])){
chk++;
}
}
}
else{chk=0;
for(intn=1;nif((a[n].equals(fenci[k]))&&(a[n-1].equals(fenci[k-1]))){
chk++;
}
}
}
System.out.println(chk);
if(chk==0){T_test=0;
break;}else{
T_test*=(double)chk/cnk;
cnk=chk;}
}
}
System.out.println("T_test="+T_test);
}
publicstaticString[]dong_split(StringstrInfo,StringstrSplit){
intsize=1;
for(intk=0;kif(strInfo.substring(k,k+1)!
=null&&(strInfo.substring(k,k+1)).equals("/")){
size++;
}
}
String[]arrRtn=newString[size];
StringstrTemp="";
intlen=strInfo.length();
intindex=0;
inti=0;
while(len>1){
index=strInfo.indexOf(strSplit);
if(index>0){
strTemp=strInfo.substring(0,index);
strInfo=strInfo.substring(index+1);
arrRtn[i++]=strTemp;
}elseif(index==0){
strInfo=strInfo.substring(index+1);
arrRtn[i++]="";
}else{
break;
}
len=strInfo.length();
}
index=strInfo.indexOf(strSplit);
if(index==0){
arrRtn[i++]="";
arrRtn[i]="";
}else{
arrRtn[i]=strInfo;
}
returnarrRtn;
}
}
程序说明:
在整个程序的编写中,我的思路就是把pku_test_gold.txt文件中每一个句子中的分词字符串存储在一个字符串数组中,然后通过与所找字符串比对,并计数。
想法很简单,但实际实施的时候遇到了些问题—怎么把文件中的分词字符串分出来。
起初我想到用java的split函数,但其中转义字符理解的不是很好。
后来就没用,而是用了一个改写的split函数实现了分词并存储。
例如”钓鱼岛/是/中国/的/国土主权/不容侵犯/”输出结果为“a[0]:
钓鱼岛a[1]:
是a[2]:
中国a[3]:
的a[4]:
国土主权a[5]:
不容侵犯”。
然后,按照2-gram法就可以输出结果。
具体实现方法如上所示。
5.实验结果及分析
紧济体质改革104372
fenci[1]:
紧
6
fenci[2]:
济
0
T_test=0.0
经济体质改革104372
fenci[1]:
经济
238
fenci[2]:
体质
0
T_test=0.0
经济体制改革104372
fenci[1]: