17、正则表达式的匹配——剑指offer

正则表达式的匹配

问题描述:请实现一个函数用来匹配包含'.'和'*'的正则表达式, 模式中的字符‘.’表示任意一个字符, 而'*'表示它前面的字符可以出现任意次(含0次)


    首先考察逻辑分析能力,具体就是分情况讨论

    本方法思想:分析过程比较复杂,可以直接先看代码,有注释,更加方便理解。

        在每轮匹配中,Patttern第二个字符是'*'时:
 *         1:第一个字符不匹配('.'与任意字符视作匹配),那么'*'只能代表匹配0次,
 *         比如'ba'与'a*ba',字符串不变,模式向后移动两个字符,然后匹配剩余字符串和模式
 *         2:第一个字符匹配,那么'*'可能代表匹配0次,1次,多次,
 *         比如'aaa'与'a*aaa'、'aba'与'a*ba'、'aaaba'与'a*ba'。

 *         匹配0次时,字符串不变,模式向后移动两个字符,然后匹配剩余字符串和模式; 

            匹配1次时,字符串往后移动一个字符,模式向后移动2个字符;

 *        匹配多次时,字符串往后移动一个字符,模式不变(先把本次的字符匹配了,然后模式串不变继续匹配剩下的字符串);
 * 
 * 
 *         而当Patttern第二个字符不是'*'时,情况就简单多了:
 * 
 *         1:如果字符串的第一个字符和模式中的第一个字符匹配,那么在字符串和模式上都向后移动一个字符,然后匹配剩余字符串和模式。

 *         2:如果字符串的第一个字符和模式中的第一个字符不匹配,那么直接返回false。

持续更新...

代码附下

Java实现:

package 正则表达式的匹配;
/**
 * 请实现一个函数用来匹配包含'.'和'*'的正则表达式 模式中的字符‘.’表示任意一个字符, 而'*'表示它前面的字符可以出现任意次(含0次)
 * 
 * @author user
 *
 *         在每轮匹配中,Patttern第二个字符是'*'时:
 * 
 *         1:第一个字符不匹配('.'与任意字符视作匹配),那么'*'只能代表匹配0次,
 *         比如'ba'与'a*ba',字符串不变,模式向后移动两个字符,然后匹配剩余字符串和模式
 *         2:第一个字符匹配,那么'*'可能代表匹配0次,1次,多次,
 *         比如'aaa'与'a*aaa'、'aba'与'a*ba'、'aaaba'与'a*ba'。
 *         匹配0次时,字符串不变,模式向后移动两个字符,然后匹配剩余字符串和模式; 匹配1次时,字符串往后移动一个字符,模式向后移动2个字符;
 *         匹配多次时,字符串往后移动一个字符,模式不变;
 * 
 * 
 *         而当Patttern第二个字符不是'*'时,情况就简单多了:
 * 
 *         1:如果字符串的第一个字符和模式中的第一个字符匹配,那么在字符串和模式上都向后移动一个字符,然后匹配剩余字符串和模式。
 *         2:如果字符串的第一个字符和模式中的第一个字符不匹配,那么直接返回false。
 */

public class MatchString {
    public boolean match(char[] str, char[] pattern) {
        if (str == null || pattern == null) {
            return false;
        }
        return matchCore(str, 0, pattern, 0);
    }

    /**
     * 
     * @param str
     *            字符串
     * @param s
     *            字符串开始匹配的下标
     * @param pattern
     *            模式串
     * @param p
     *            模式串开始匹配的下标
     * @return
     */
    private boolean matchCore(char[] str, int s, char[] pattern, int p) {
        // TODO Auto-generated method stub
        if (str.length == s && pattern.length == p) {
            return true;// 都匹配完毕
        }
        if (str.length > s && pattern.length == p) {
            return false;// 模式串匹配完,但是还有字符串
        }
        // 如果字符串匹配完毕
        if (str.length == s) {
            if (pattern.length - p > 2) {// 模式串还有多余两个字符串,那一定错误
                return false;
            }
            if (pattern.length - p == 2 && pattern[p + 1] == '*') {// 如果模式串还有两个,并且第二个为*则返回正确
                return true;
            }
            return false;
        }
        if (p + 1 < pattern.length && pattern[p + 1] == '*') {// pattern第二个为*时
            if (str[s] == pattern[p] || pattern[p] == '.') {
                // 第一个字母相等的情况下
                return matchCore(str, s + 1, pattern, p + 2) || matchCore(str, s + 1, pattern, p)
                        || matchCore(str, s, pattern, p + 2);
            } else {
                // 首字母不匹配
                return matchCore(str, s, pattern, p + 2);
            }
        }
        // 第二个字母不是*的情况下
        if (str[s] == pattern[p] || pattern[p] == '.') {
            return matchCore(str, s + 1, pattern, p + 1);
        }
        return false;
    }


    public static void main(String[] args) {
        String string = new String();
        string = "abc";
        char str[] = string.toCharArray();
        String patt = new String();
        patt = "a*b*cc";
        char pattern[] = patt.toCharArray();
        MatchString match = new MatchString();
        System.out.println(match.match(str, pattern));
    }
}

持续更新...欢迎赞赏!

https://blog.csdn.net/ustcer_93lk/article/details/80372769

如果有问题,欢迎大家留言,有更好的方法也期待大家告知。

猜你喜欢

转载自blog.csdn.net/ustcer_93lk/article/details/80372769