最近忙于一个搜索项目,忙里偷闲,记下其中的一个花絮。
在检索式中,有一种关系运算的命令需要解析,以备检索之用。如:
WordA 5W WordB
这表示WordA和WordB之间可以出现0到5个任意词汇,且WordA和WordB的顺序不能改变。而“5W”,就是一个关系运算的命令。
所有的关系运算命令用正则表达式来表达,就是:
︹(=|ε)[0-9]?[0-9]?(D|W) ︹
其中︹为空格,强制如此是为消除词法歧义。这个正则表达式用NFA表达很自然的就是:
F( 1, ︹) = 2
F( 2, =) = 3
F(2, ε) = 3
F(3, [0-9]) = 4
F(3, ε) = 5
F(4, [0-9]) = 5
F(4, ε) = 5
F(5, D) = 6
F(5, W) = 6
F(6, ︹) = 7
把NFA转化为等价的DFA,可以首先计算状态集合{1,2,3,4,5,6,7}的每个元素的closure集及新的边集(状态转换函数)。
Closure(1) = {1}
Closure(2) = {2,3,5}
Closure(3) = {3,5}
Closure(4) = {4,5}
Closure(5) = {5}
Closure(6) = {6}
Closure(7) = {7}
则等价的DFA可表示为:
Fd( {1},︹) = {2,3,5}
Fd( {2,3,5}, =) = {3,5}
Fd( {2,3,5}, [0-9]) = {4,5}
Fd( {2,3,5}, D|W ) = {6}
Fd( {3,5}, [0-9]) = {4,5}
Fd( {3,5}, D|W ) = {6}
Fd( {4,5}, [0-9]) = {5}
Fd( {4,5}, D|W ) = {6}
Fd( {5}, D|W ) = {6}
Fd( {6}, ︹) = {7}
在命令中,W表示前后词汇的顺序不变,D表示前后词汇的顺序可以交换。‘=’表示两词汇之间(必须)跨越n个词汇,n的值由数字来表达(若不存在则为0)。没有‘=’则表示可以跨越任意0到n个词汇。
这是正则表达式的一个简单应用。命令的识别算法由其DFA形式较容易实现。问题的难度在于,对于一个含有关系运算命令的词汇序列,如何进行有效的检索?这个算法才是很有意思的。
不过作为花絮,我所要提出的问题并不是这一个,事实上问题是:
词汇序列中的词汇支持模糊查询,例如lieve 可以匹配 +li??e+#,而不能匹配+li?? #e+#,这其中有三种模糊查询命令字符,‘+’表示任意0到n个字符,‘?’表示0或1个字符,‘#’表示1个字符。此时词汇的模糊查询与词序列的关系运算同时存在,如何设计高效率的检索算法?
有时间不妨思考之^_^.