剑指offer(55):正则表达式匹配

来源:互联网 发布:windows 10没远程桌面 编辑:程序博客网 时间:2024/05/21 20:28

题目描述

请实现一个函数用来匹配包括’.’和’*’的正则表达式。模式中的字符’.’表示任意一个字符,而’*’表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串”aaa”与模式”a.a”和”ab*ac*a”匹配,但是与”aa.a”和”ab*a”均不匹配。

分析

思路来源于剑指offer书籍,理解的还不是很透彻。

每次从字符串里拿出一个字符和模式中的字符去匹配。如果模式中的字符ch是’.’,那么它可以匹配字符串中的任意字符。如果模式中的字符ch不是’.’,而字符串中的字符也是ch,则它们同样相互匹配,接着匹配后面的字符。

当模式中的第二个字符不是’*’时,比较简单。如果字符串中的第一个字符和模式中的第一个字符相匹配,那么字符串和模式上都向后移动一个字符,然后匹配剩余的字符串和模式。如果字符串中的第一个字符和模式中的第一个字符不匹配,则直接返回false。

当模式中的第二个字符是’*’,比较复杂,可能有多种匹配方法。一个选择是在模式上向后移动两个字符。这相当于’*’和它前面的字符被忽略掉了,因为’*’可以匹配字符串中的0个字符。如果模式中的第一个字符和字符串中的第一个字符相匹配时,则在字符串向后移动一个字符,而在模式上有两个选择:向后移动两个字符,或者保持模式不变。

匹配状态
模式ba*ab的非确定有限状态机。当匹配进入状态2并且字符串的字符是’a’时,有两个选择:进入状态3,或者回到状态2。

当匹配进入状态2并且字符串的字符是’a’时,有两个选择:进入状态3(在模式上向后移动两个字符),或者回到状态2(模式保持不变)。

牛客AC:

package com.problem;/** * 请实现一个函数用来匹配包括'.'和'*'的正则表达式。 * 模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 *  在本题中,匹配是指字符串的所有字符匹配整个模式。 *  例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配 *   * @author Administrator * */public class RegexMatch {    public boolean match(char[] str, char[] pattern) {        return isMatch(str, 0, pattern, 0);    }    public boolean isMatch(char[] str, int strIndex, char[] pattern, int patternIndex) {        if (strIndex == str.length && patternIndex == pattern.length)   // 同时结束            return true;                if (patternIndex >= pattern.length)     // pattern 先结束            return false;        if (strIndex == str.length)     // str结束            return false;        // patternIndex 还没到达倒数第二位        if (patternIndex < pattern.length - 1) {            // 如果下一位是 *            if (pattern[patternIndex + 1] == '*') {                if ((strIndex < str.length) &&                         (str[strIndex] == pattern[patternIndex] || pattern[patternIndex] == '.')) {                            // 第一种,模式上移动两个字符,相当于忽略‘*’和它前面的字符                    return isMatch(str, strIndex, pattern, patternIndex + 2) ||                                 // 第二种,当前字符匹配成功,模式上移动两个字符                            isMatch(str, strIndex + 1, pattern, patternIndex + 2) ||                             // 第三种,当前字符匹配成功,模式上保持不变                            isMatch(str, strIndex + 1, pattern, patternIndex);                } else                    // 忽略'*'和它前面的字符                    return isMatch(str, strIndex, pattern, patternIndex + 2);            }        }        // 下一位不是‘*’,则只要匹配'.',匹配成功后,同时移动一个字符        if (str[strIndex] == pattern[patternIndex] || pattern[patternIndex] == '.')            return isMatch(str, strIndex + 1, pattern, patternIndex + 1);        return false;    }}

参考
1. 何海涛,剑指offer名企面试官精讲典型编程题(纪念版),电子工业出版社

0 0
原创粉丝点击