|
下面的算法需要对Regex作变换,从而改变括号的标号,因此,采用新的写法。Regex中的捕获组用一个足够大的和字母表不相交的变量集Γ中的变量x表示,变量的捕获写作(e)%x;变量的引用直接写作x。
没有%x的括号只指示优先级。
如:\((a^{\ast}) (a|b) \backslash 1 \Rightarrow (a^{\ast}) \%x (a|b) x\)
问题
关于这个问题,此前[1]的做法是把问题转换到SpLog,而[2]中对确定型的vsf的一种类似判定是通过TMFA完成的。下面给出的是一种通过直接在regex层面变换,最后转换为Word Equation求解的判定方法。
首先,观察到regex的几个性质:
引理
换言之,regex和传统正规表达式的区别其实不来自于逆引用本身,而是逆引用和Star同时作用的结果。
例
引理
换言之,我们可以安全地假设变量的捕获和引用在每一个alternation的同一个析取支内。
引理
一个例子:
例
下面,非形式化地简述判定算法的基本思路:
使用一种迭代过程,将regex u和v都变换为一种等价的范式。这种范式类似于析取范式,要求regex由一系列alternation组成。即\(a = b_1 |b_2 | \ldots |b_m\),其中,每一个b中,alternation只在Star中出现。
更进一步,要求将每一个析取支b化为\(e_1 e_2 \ldots e_n\)的形式。其中,每一个e如果是变量的捕获(e)%x,则e必定是一个Kleene Star。
分别从u和v的范式中不确定地选择一个析取支\(b_u\)和\(b_v\)。
通过一个简单的过程,将\(b_u\)和\(b_v\)分别转化为带正则约束的word equation。已知此理论是可判定的,因此使用一种已有的判定算法解之,即可判定VSF相交的非空性。
首先给出一个例子说明迭代过程是如何工作的:
例
现在,alternation只出现在Star和x的捕获中,对变量x的捕获,通过变量重命名展开其顶层的alternation:
现在已经得到了析取形式的等价regex,但是还不满足捕获的表达式一定是Star。因此进一步展开concatenation:
这样就得到了原式的一个等价形式,由一系列alternation连接的表达式组成,每一个表达式中都只存在对Star的捕获。
下面是一个归约到word equation的例子:
例
定义
\(\alpha := \alpha_1 \alpha_2 | \alpha_1 + \alpha_2 | \beta^{\ast} | (\alpha) \%x|x|c| \varepsilon\)
\(\beta := \beta_1 \beta_2 | \beta_1 + \beta_2 | \beta^{\ast} |c| \varepsilon\)
对于一个输入的vsf regex,首先删除其所有语法上冗余的变量(即「左侧」没有捕获的变量),以及满足引理2或3条件的变量和捕获。将简化后的regex输入后续例程。
定义
定义
如果\(u = e_1 + e_2\),则\(T (u) = T
(e_1) + T (e_2)\)
如果\(u = e_1 e_2\)
假设\(T (e_1) = \Sigma^n_1 s_i, T (e_2) = \Sigma^m_1
t_j\)。定义Q为u中所有同时出现引用和捕获的变量集,\(\Gamma_i\)为\(s_i\)中被捕获的变量集,\(S_{i
j} = s_i \circ t_j [\varepsilon / Q -
\Gamma_i]\),其中\([x /
y]\)表示y替换为x。
则有\(T (u) = \Sigma_i \Sigma_j S_{i j}\)
否则\(T (u) = u\)
引理
v是伪析取范式
对任意变量x,每一个析取支内最多出现一次x的捕获
对任意变量x,如果x的捕获在u中出现,且v的一个析取支内出现x的引用,则必定也出现x的捕获,且在引用之前出现。
证明. 对u应用结构归纳法。
基础情况比较简单,容易验证。
当\(u = e_1 + e_2\),由归纳条件可知\(T (e_1) 、T (e_2)\)都是伪析取范式,所以T(u)也是。
考虑条件2,对任意变量x,由归纳条件知\(T (e_1) 、T (e_2)\)内最多出现1次x的捕获,由于T(u)的析取支就是二者的析取支的并,所以T(u)也满足条件2。
考虑条件3,如果x的捕获在u中出现,分两种情况:如果捕获是在\(e_1\)中出现,则若v的一个析取支内有x,根据简化规则,此析取支必然来自\(\)\(T (e_1)\),则由归纳条件知3成立;如果捕获是在\(e_2\)中出现,则若v的一个析取支内有x,根据简化规则,此析取支必然来自\(T (e_2)\),同样地,由归纳条件知3成立。
当\(u = e_1 e_2\),由归纳条件知\(T (e_1) 、T (e_2)\)中都不含alternation的自由出现.因为T(u)是\(T (e_1) 、T (e_2)\)析取支的组合,所以也必然不含alternation的自由出现。
考虑条件2,由条件2的归纳条件知,对任意变量x,每一个s和t中都最多有一个x的捕获。由于输入的u中同一个变量只有一个捕获,所以s和t不可能同时有捕获,所以v的析取支中也最多有一个捕获。
考虑条件3,假设x的捕获在u中出现。
如果出现在\(e_1\)中,且v中一个析取支有x的引用,那么存在i,j使得\(S_{\operatorname{ij}}\)中有x的引用。如果此引用是在\(s_i\)中,则有归纳条件可知3成立,如果此引用是在\(t_j [\varepsilon / Q - \Gamma_i]\)中,那么x必然在\(\Gamma_i\)中,从而x必然在s中被捕获,因此3成立。
如果出现在\(e_2\)中,且v中一个析取支有x的引用,那么同样存在i,j使得\(S_{\operatorname{ij}}\)中有x的引用。此时根据归纳条件即可知3成立。
得到伪析取范式u后,u中可能含有同一个变量的多次捕获,但这些捕获一定在不同的析取支内。因此,之后先要对所有变量进行一次换名,保持捕获的唯一性。具体做法略。
定义
算法
对任意伪析取范式u,设\(u = a_1 + \cdots + a_n\)。对每个析取支a,找出所有的捕获b=(e)%x,并作如下变换:
如果e是单字符c,则将b和析取支a中所有的x替换为c.
如果e是空,则从a中删去b和所有x。
如果e是\(e_1 e_2\),则将a替换为\(a [(e_1) \%x_1 (e_2) \%x_2 / b, x_1 x_2 / x]\)
如果e是\(e_1 + e_2\),则将a替换为两个析取支p和q,其中\(p = a [(e_1) \%x_1 / b, x_1 / x], q = a [(e_2) \%x_2 / b, x_2 / x]\)。
如果e是\((e') \%y\),则将a替换为\(a [e / b, y / x]\)
如果e是变量\(y\),则将a替换为\(a [y / b, y / x]\)
重复上述步骤,直到所有捕获的表达式都是Star,停止。
引理
证明. 变换后是析取范式从算法的结束条件即可知;而上述的几步都不改变Star内部的结构,因此vsf性质保持。关键在于算法一定终止:
对每个析取支,每次迭代都将其中的一个捕获的表达式简化一层,同时捕获数量最多加一。因此,算法的迭代次数只取决于所有捕获的表达式的语法树中非Star节点的最大层数。(复杂度待分析)
算法
对于范式u的一个析取支a=\(e_1 e_2 \ldots e_n\),令特殊的变量w代表输入串,定义初始约束为S={\(w = x_1 + x_2 + \cdots + x_n\)}。对每一个\(e_i\),作如下操作:
如果\(e_i\)是变量x或者单字符c,则\(S = S \cup x_i = e_i\)。
如果\(e_i\)是Kleene Star,则\(S = S \cup x_i \in L (e_i)\)
如果\(e_i\)是(e)%x,则\(S = S \cup x \in L (e) \cup x_i = x\)
最后得到的S就是a对应的word equation。
总判定算法:
算法
输入vsf regex u和v。
依次对u和v应用简化过程、算子T、换名过程以及算法1,得到u和v的析取范式\(u' = a_1 + \cdots + a_n\)和\(v' = b_1 + \cdots + b_m\)。
非确定地从u的n个析取支中选择一支a,以及从v的m个析取支中选择一支b。对a和b应用算法2,得到约束\(S_a\)和\(S_b\)。
应用word equation的求解过程,求解\(S_a \cup S_b\)。如果有解,则输出YES,否则输出NO。