8楼的代码,因为findstr 的一些特性,存在一些bug,修改如下:
一、词库搜索代码:
findstr /x /g:fen.tmp /f:dics.txt
二、把词库按字数分别存放,并且文件名上可见词的字数。如:
[email=dict@1.txt]dict@1.txt[/email]
1人
1们
...
[email=dict@2.txt]dict@2.txt[/email]
2人民
2后门
...
......
些种办法把词分出来后,可方便词库的维护。
以下代码可把楼主提供的词库转换成按字数分文档存放。 | @echo off&setlocal enabledelayedexpansion | | | | for /l %%a in (0,1,10) do del dict@%%a.txt /q | | | | echo;%time% | | for /f "tokens=*" %%a in (dic16.txt) do ( | | set str=%%a | | if "!str:~9!" equ "" ( | | set str=0123456789%%a | | set n=!str:~-10,1! | | echo;!n!%%a>>dict@!n!.txt | | ) else ( | | echo;!n!%%a>>dict@10.txt | | ) | | ) | | (for /f %%a in (dictionar@1.txt) do (echo;1%%a))>dict@1.txt | | dir /o-n /b dict@*>dics.txt | | echo;%time% | | pauseCOPY |
三、dics.txt 存放各分词库的文件名,以字数长的分词库在前,短在后。
dics.txt内容:
[email=dict@10.txt]dict@10.txt[/email]
[email=dict@9.txt]dict@9.txt[/email]
[email=dict@8.txt]dict@8.txt[/email]
[email=dict@7.txt]dict@7.txt[/email]
[email=dict@6.txt]dict@6.txt[/email]
[email=dict@5.txt]dict@5.txt[/email]
[email=dict@4.txt]dict@4.txt[/email]
[email=dict@3.txt]dict@3.txt[/email]
[email=dict@2.txt]dict@2.txt[/email]
[email=dict@1.txt]dict@1.txt[/email]
四、分词代码修改后,不再有搜索漏网的bug。并且对速度影响不大,20个字数长度的句子,拆分用时在一秒内。 | @echo off&setlocal enabledelayedexpansion | | | | :lp | | set str= | | echo; | | echo;直接回车退出测试 | | set /p str=输入一个字符串: | | set ti=%time% | | if "!str!" equ "" goto :eof | | setlocal enabledelayedexpansion | | | | | | set/a z=8180,x=0&for /l %%a in (1,1,14) do (set/a "y=(z-x)/2+x" | | for %%b in (!y!) do if "!str:~%%b,1!" equ "" (set/a z=y) else (set/a x=y) | | ) | | ::计算输入串的长度 | | | | ::sap 存入同等长度的空格串 | | set lens=1 2 3 4 5 6 7 8 9 10 11 | | set/a z1=z-1 | | set sap= | | (for /l %%i in (0,1,!z1!) do ( | | set "spa= !spa!" | | set one=!str:~%%i,1! !one! | | set/a x=z-%%i | | for %%j in (!lens!) do ( | | set/a y=%%i+%%j | | echo;%%j!str:~%%i,%%j! | | for %%a in ("!str:~%%i,%%j!") do ( | | set ##%%~a=%%i-!y!-%%j !##%%~a! | | ) | | ) | | ))>fen.tmp | | | | ::(for /l %%a in (0,1,!z!) do for %%k in (!@%%a!) do (echo;%%k))>fen.tmp | | ::进行排列拆分到临时文件fen.tmp,同时取各分词的长度,及在原句中的起址位置,并按一定的规则保存 | | ::似乎要从短到长,findstr才能完全正确查找 | | | | | | set var=!str! | | echo;!vvv! | | | | for /f "tokens=2* delims=:123456789" %%1 in ('findstr /x /g:fen.tmp /f:dics.txt') do ( | | for %%k in (!##%%2!) do ( | | if "!var:%%2=!" neq "!var!" ( | | for /f "tokens=1,2,3 delims=-" %%b in ("%%k") do ( | | if "!var:~%%b,%%d!" equ "!str:~%%b,%%d!" ( | | echo;截取过程:[!var!] %%2 | | set var=!var:~0,%%b!!spa:~,%%d!!var:~%%c! | | set $$%%b= [%%2] | | ) | | ) | | ) | | ) | | ) | | ::搜索词库,并做已经截取过记号,同时为恢复分词在原句中的位置做准备 | | | | | | echo; | | if "!var: =!" neq "" ( | | echo;词库中没有的: | | for %%a in (!var!) do ( | | for %%k in (!##%%a!) do ( | | if "!var:%%a=!" neq "!var!" ( | | for /f "tokens=1,2,3 delims=-" %%b in ("%%k") do ( | | if "!var:~%%b,1!" neq " " ( | | echo;截取过程:[!var!] %%a | | set var=!var:~0,%%b!!spa:~,%%d!!var:~%%c! | | set $$%%b= %%a | | ) | | ) | | ) | | ) | | ) | | ) else (echo;所有字符均可在词库中找到) | | ::对在词库中找不到的分词,也进行同样的处理 | | | | echo; | | set dest= | | for /l %%a in (0,1,!z!) do set dest=!dest!!$$%%a! | | echo;最终拆分:!dest! | | echo;%ti% | | echo;%time% | | endlocal&goto :lpCOPY |
五、词在库中的先后,决定了匹配的优先顺序,只要改变词在库中的顺序,即可改变折分的准确性。
我另外写了一个词库维护的代码,可以改变词在库中的顺序,增加词到词库中。
初版只支持一次修改两个词顺序。代码如下: | @echo off&setlocal enabledelayedexpansion | | | | echo; ** 调整词序/增加词组 ** | | set /p str1=输入第一字符串: | | set /p str2=输入第二字符串: | | if "!str1!" equ "!str2!" goto :eof | | | | set str=0123456789!str1! | | set n1=!str:~-10,1! | | | | set str=0123456789!str2! | | set n2=!str:~-10,1! | | | | set str1=!n1!!str1! | | set str2=!n2!!str2! | | | | if "!n1!" equ "!n2!" ( | | findstr /x "!str1!" dict@!n1!.txt>nul | | if !errorlevel! equ 1 ( | | set str1=%str2% | | set str2=%str1% | | set xchg=y | | findstr /x "!str1!" dict@!n1!.txt>nul | | if !errorlevel! equ 1 set xchg=n | | ) | | | | if "!xchg!" neq "n" ( | | copy dict@!n1!.txt fen.tmp /y | | (for /f %%a in (fen.tmp) do ( | | if "%%a" neq "!str2!" echo;%%a | | if "%%a" equ "!str1!" ( | | echo;!str2! | | if defined xchg (echo;!str1!) | | ) | | ))>dict@!n1!.txt | | echo;修改 [!str1!] 和 [!str2!] 在dict@!n1!.txt中的顺序 | | ) else ( | | echo;!str2!>>dict@!n1!.txt | | echo;!str1!>>dict@!n1!.txt | | echo;添加 [!str1!] 和 [!str2!] 到 dict@!n1!.txt | | ) | | | | ) else ( | | findstr /x "!str1!" dict@!n1!.txt>nul | | if !errorlevel! equ 1 ( | | echo;!str1!>>dict@!n1!.txt | | echo;添加 [!str1!] 到 dict@!n1!.txt | | ) | | findstr /x "!str2!" dict@!n2!.txt>nul | | if !errorlevel! equ 1 ( | | echo;!str2!>>dict@!n2!.txt | | echo;添加 [!str2!] 到 dict@!n2!.txt | | ) | | ) | | | | pauseCOPY |
拆分句子示例:
输入一个字符串:这也是造成肇事车辆屡屡逃逸的一个主要原因
截取过程:[这也是造成肇事车辆屡屡逃逸的一个主要原因] 主要原因
截取过程:[这也是造成肇事车辆屡屡逃逸的一个 ] 屡屡
截取过程:[这也是造成肇事车辆 逃逸的一个 ] 车辆
截取过程:[这也是造成肇事 逃逸的一个 ] 逃逸
截取过程:[这也是造成肇事 的一个 ] 一个
截取过程:[这也是造成肇事 的 ] 也是
截取过程:[这 造成肇事 的 ] 造成
截取过程:[这 肇事 的 ] 肇事
截取过程:[这 的 ] 这
截取过程:[ 的 ] 的
所有字符均可在词库中找到
最终拆分: [这] [也是] [造成] [肇事] [车辆] [屡屡] [逃逸] [的] [一个] [主要原因]
开始: 6:44:02.45
结束: 6:44:03.20
楼主出的测试例子结果如下(词库的一些词经过顺序调整):
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京] [天安门] [门楼] [的] [门]
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京] [大学生活动中心] [门楼] [的] [门]
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京大学] [生活] [在] [音乐] [里]
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京大学] [生活] [很好]
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京大学] [的] [学生] [生活] [在] [音乐] [里]
最终拆分: [我] [喜欢] [坐在] [面包车] [上] [一边] [吃] [面包] [一边] [看] [北京大学] [的] [学生] [活在] [音乐] [里]
最终拆分: [广西] [大学生活] [很好]
最终拆分: [我] [喜欢] [吃] [鸭肉]
最终拆分: [伟] [大学生] [生活]
最终拆分: [大学生活] [动]
最终拆分: [大学生活] [好]
最终拆分: [大学生活动中心]
最终拆分: [发展] [中国家庭养猪] [事业]
最终拆分: [你说] [的] [确实在] [理]
[ 本帖最后由 netbenton 于 2010-9-17 07:31 编辑 ] |