C排名第一,该题是《HJ71 字符串通配符》的简化版本。不用动态规划和递归,用双指针回溯法,只遍历一次,不占用额外空间。由于模式串中的字符 '*' 表示它前面的字符可以出现任意次,为了方便处理 '*' 和它前面的字符,在这里逆序匹配字符。
思路:
指针 i,j 分别表示 str 串和 pattern 串当前字符的位置,从后向前按匹配规则匹配,直至 str 串访问完毕。
判断条件:当遇到 pattern 串的 '*' 时,用 i_prev 和 j_prev 记录当前 str 串和 pattern 串字符位置,此时 j 指向 '*' 前面的字符,对比 i 所指字符是否相同:
- 若不同,该 '*' 作废, i 不变,j 前移一位,继续按匹配规则匹配;
- 若相同, i 不变,j 前移一位,继续按匹配规则匹配(开始时 '*' 的匹配数为0)。当之后遇到匹配错误的情况,回溯 i_prev 和 j_prev 记录的值返还给 i,j,此时 i 前移一位,'*' 的匹配数+1,回到判断条件继续判断;
若 str 串与 pattern 串都访问完毕则匹配成功,若 pattern 串还有剩余,则判断接下来的剩余串是否是 "...x*x* " 类型的组合,是则匹配成功,不是则匹配失败。
代码:
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param str string字符串 * @param pattern string字符串 * @return bool布尔型 */ bool match(string str, string pattern) { // write code here int i=str.size()-1,j=pattern.size()-1;//逆序匹配 int i_prev,j_prev,flag=0;//i_prev,j_prev指针用来回溯,flag为回溯标志 while(i>-1){//str串匹配到头就结束 if(str[i]==pattern[j] || pattern[j]=='.'){ i--;j--; } else if(pattern[j]=='*'){ if(str[i]!=pattern[j-1] && pattern[j-1]!='.'){//若'*'前面的字符不匹配,pattern的指针前移 j-=2; } else{//若'*'前面的字符可以匹配,则从匹配0个字符开始,直至遇到之后不匹配时回溯,i_prev,j_prev为回溯指针 i_prev=i; j_prev=j; j-=2; flag=1; } } else if(flag){//出现字符不匹配情况,回溯 i=i_prev-1;//回溯之后'*'的匹配数+1 j=j_prev; flag=0; } else{ return false; } } while(j>-1){//若pattern串还有字符,则只要出现非'*'字符单走就一定匹配失败 if(pattern[j]!='*' && pattern[j+1]!='*'){ return false; } j--; } return true; } };