首页 / 博客 / 图片翻译 / 音视频翻译 / 支持 / 捐助 / 订阅
BasicCAT开发笔记(六):SRX的算法实现
前文介绍了Lisa的三大翻译标准,我发现分割句段还是应该使用SRX提供的方法。毕竟它是一个标准,可以直接利用前人做好的规则文件,与其它CAT软件也可以进行分割规则的交换。
SRX提供的伪代码看起来很简单,但实现起来我感到有点难度。主要是它需要检查分割点前后的内容,这可以用正则的lookahead和lookbehind来实现,但遍历文本时后面有多少长度的文本要作为afterbreak检测的对象则不能确定。
于是我找了一些开源项目,主要有segment、omegat以及heartsome。其中omegat使用的规则文件并不是正宗的srx格式,但基本保持了srx的设计。
下面讲一下我参考OmegaT的源码得出的自己的SRX算法实现。
先读取SRX文件,把分割规则和例外规则分开存放。然后依次遍历这些规则,将符合要求的断句位置存放进一个列表。有些规则可能没有beforebreak或者afterbreak,这时处理很简单,匹配到后直接将位置信息进行存储即可。而如果两个break齐全的话,先寻找所有的beforebreak匹配的内容,匹配到一条beforebreak,就开始寻找afterbreak的匹配,然后看看这两个匹配是不是接壤。如果是则记录位置信息。
为了提高效率,每次匹配后,该条规则中需要匹配的文本要去除匹配位置前的内容,而循环到下一条规则的文本时还是要从原来的文本开始。
For Each rule As Map In rulesList
textLeft=text
Dim beforeBreak,afterBreak As String
beforeBreak=rule.Get("beforebreak")
afterBreak=rule.Get("afterbreak")
Dim bbm As Matcher
bbm=Regex.Matcher2(beforeBreak,32,textLeft)
If beforeBreak<>"null" Then
Do While bbm.Find
If afterBreak="null" Then
breakPositions.Add(bbm.GetEnd(0)+text.Length-textLeft.Length)
textLeft=textLeft.SubString2(bbm.GetEnd(0),textLeft.Length)
bbm=Regex.Matcher2(beforeBreak,32,textLeft)
End If
Dim abm As Matcher
abm=Regex.Matcher2(afterBreak,32,textLeft)
Do While abm.Find
If bbm.GetEnd(0)=abm.GetStart(0) Then
breakPositions.Add(abm.GetEnd(0)+text.Length-textLeft.Length)
textLeft=textLeft.SubString2(abm.GetEnd(0),textLeft.Length)
abm=Regex.Matcher2(afterBreak,32,textLeft)
bbm=Regex.Matcher2(beforeBreak,32,textLeft)
Exit
End If
Loop
Loop
Else if afterBreak<>"null" Then
Dim abm As Matcher
abm=Regex.Matcher2(afterBreak,32,textLeft)
Do While abm.Find
breakPositions.Add(abm.GetEnd(0)+text.Length-textLeft.Length)
textLeft=textLeft.SubString2(abm.GetEnd(0),textLeft.Length)
abm=Regex.Matcher2(afterBreak,32,textLeft)
Loop
End If
Next
得到需要断句和不需要断句的位置列表后,我们对两个列表进行比对,生成一个不包含例外位置的断句位置列表。然后就可以根据位置信息确定片段了。
Dim finalBreakPositions As List
finalBreakPositions.Initialize
For Each index As Int In breakPositions
If nonbreakPositions.IndexOf(index)=-1 Then
finalBreakPositions.Add(index)
End If
Next
这一方法不需要使用复杂的正则表达式,比较简单明了,但效率不高。如果遇到大段文字,需要先把文章分成段落等小的片段,这时的断句效率还是很可观的。我测试80000词的《哈利波特与魔法石》需要18秒时间。因为考虑了所有的规则,所有相当于cascade没有勾选。
而要实现cascade勾选的模式,需要按照SRX给出的算法,在每个字符串的位置上都匹配一遍规则,而且是优先匹配例外规则,效率会更低。
相关文件:
https://github.com/xulihang/BasicCAT/blob/master/BasicCAT/SRX.bas
https://github.com/xulihang/BasicCAT/blob/master/BasicCAT/segmentation.bas
© 2025 BasicCAT ― Powered by Jekyll and Textlog theme