以前在做“Valid Number”这道题的时候,各种corner case,代码又长又乱。后来上网搜了下,有大神用有限状态自动机(FSA)给了解法。真是neat & elegant,实在佩服。后来想到这种方法也可以用来解决“Wildcard Matching”。具体思路如下:
首先构造FSA:假设pattern为”c*a?d”,假设初始状态为1,读取”c”之后变为状态2,状态2读取”a”变为状态3,或者读取任意多字符后留在状态2;状态3读取任意一个字符后变为状态4;状态4读取”d”之后变为状态5。状态转换图如下所示:
然后遍历字符串s,如果s[i]是某个英文字符或者”?”,就判断当前状态下能不能通过s[i]进入下一状态,如果可以,就递归下去;如果s[i]是”*“,就继续递归判断s[i+1]和当前状态。代码如下:
这个方法的问题是对于pattern里面的”*“,递归次数太多,提交的时候超时了。所以想了一些剪支方法:
- 如果某个时刻s[i]已经是FSA里的最后一个状态,但s还没有遍历完,这时只要看pattern的最后一个元素是否是”*“即可;
- 一般的状态(最后一个状态除外)要么有两个出口(”*“和英文字母,或”*“和”?”)要么有一个出口(英文字母或”?”)。对于两个出口中”*“和英文字母的情况,要找出s[i]后面每一个和那个英文字母相等的地方,只要在那些地方遍历即可
不过改进后还是超时。。。