通配符匹配过程中必定会出现搜索

本文深入探讨了通配符在字符串匹配中的应用,通过定义特定的代数结构来简化模式串,并尝试构建适用于通配符匹配的自动机。重点讨论了在处理不确定通配符时的状态转移问题,以及如何通过搜索算法解决匹配冲突。此外,文章引入了'字符黑洞'的概念,提供了一种有效解决通配符匹配问题的贪心策略。最后,通过自动机描述了字符黑洞的行为,为实现高效匹配提供了理论基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义如下通配符:

? : 代表任意出现了一次的字符;

* : 代表出现任意长度的字符串,长度可以为0;


现在,研究一下这两个符号的代数关系,定义如下代数结构:

+_0 = * :  代表出现任意长度至少为0的字符串

+_1 = ?* = *? = ?+_0 = +_0? : 代表出现任意长度至少为1的字符串

+_k = ?+_(k-1) = +_(k-1)? : 代表出现任意长度至少为k的字符串;


并且存在以下代数关系:

+_n +_m = +_{n+m}


这样,根据以上代数结构,就可以把输入模式串化简为只含+_n, ?和已知字符的组合。接下来,根据通常做法,我们开始试图构建用于字符串匹配的自动机,很明显,对于已知字符和?,状态转移是明确的,但是对于+_n这样的不确定通配符,状态转移明显没有统一的标准,考虑以下例子:

输入串: {长度为n的不含x的已知字符串}xb{长度为m-2的不含x的已知字符串}xc.

模式串A:+_{m+n}xc

模式串B:  +_nxb+_mxc

很明显,两个模式都应该得到匹配,但是我们却无法确立一个统一的标准。比如说,当你的状态机当前模式是+_k时,你唯一知道的就是当遇到某个x时,匹配应当终止,但是却无法确定究竟选择哪一个x:是选择最远出现的那个x还是最近出现的?在以上的例子中,任意一种选择都会在满足一个模式串的时候违背另一个。


出现这个困境的原因在于,当我们仅仅依靠x的位置信息时,是无法确定匹配是否应当终止的,我们还必须要“往后看”。也就是说,仅仅检查x是否匹配是不够的,还应当进一步检查x以后的串是否匹配了——事实上,我们在检查两个+_之间的串是否存在匹配:具体的说,如果我们有串+_m{s}+_n,那么实际上,我们就是去输入串中找{s},但是必须保证找到的{s}前面至少有m个字符,后面至少有n个字符,但是通常来说,情况要更复杂,模式串一般具有如下标准形式:

+_{m1}{s1}+_{m2}{s2}...+_{mk}{sk}...+_{mn}{sn},

所以,所谓通配符匹配,实际上就是找到所有可能的{si}的位置,并且这些位置的安排不和+_{mi},+_{mi+1}所造成的约束产生冲突. 目前来看,能解决这个问题的只有搜索算法。因为这相当于求解si.pos的合理取值(所有可能的取值来源于对si的模式匹配),以满足以下不等式组:

si.pos>=mi+1

si.pos<=L-mi

s(i+1).pos>=si.pos+si.length+m(i+1) (*)

注意到,搜索的主要时间将花费在求解(*)式上,这是一个差分约束系统。如何求解这个约束系统?如果我们直接通过类似KMP那样的算法找出所有可能的si.pos取值,则必定会浪费大量的计算时间,因为有些取值本身就导致si之间互相重合。


字符黑洞:

这是一种更有效的方法,直接利用(*)式的单调性——如果我们已知了s(i-1).pos,那么确定si.pos的过程无非就是确定+_(mi)终止时,对应的字符匹配是哪一位,换句话说,如果遇到的字符是不匹配的,那么我们完全可以将它纳入+_所涵盖的字符串中,然后在从头开始试图匹配。这个过程就像一个字符黑洞在不断的吞噬无法匹配的字符,直到最后完全匹配。那么,这种贪心策略是正确的吗?事实上,我们可以用一个自动机来描述这个黑洞的行为:

黑洞起始状态为+_i后第一个已知字符;

随后的状态转移,当读入字符和模式{si}完全比配时才进入下一状态,否则统统退回起始状态(这时已读入的字符被认为吸入黑洞中);

可见模式si要么被完全匹配,所以si.pos也可以确定了,可以进入下一阶段(黑洞+_(i+1));要么匹配失败,被吸入黑洞吞噬的字符使得剩下的字符长度已不足以构建完整的si串以及其后面的+_m(i+1)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值