【字符串】B053_LC_模式匹配(思维题 = 分类讨论)

一、Problem

你有两个字符串,即pattern和value。 pattern字符串由字母"a"和"b"组成,用于描述字符串中的模式。例如,字符串"catcatgocatgo"匹配模式"aabab"(其中"cat"是"a",“go"是"b”),该字符串也匹配像"a"、"ab"和"b"这样的模式。但需注意"a"和"b"不能同时表示相同的字符串。编写一个方法判断value字符串是否匹配pattern字符串。

输入: pattern = "abba", value = "dogcatcatdog"
输出: true

提示:

0 <= len(pattern) <= 1000
0 <= len(value) <= 1000
你可以假设pattern只包含字母"a"和"b",value仅包含小写字母。

二、Solution

方法一:分类讨论

  • 当模式串 p 为空时,待匹配串 v 也应当为空
  • 当待匹配串 v 为空时,模式串 p 中的字符应只有一种
  • 当字符 a/b 的数量为 0 时,待匹配串 v 中每一段长为 vLen/x 的子串都应该相同(x 为 a/b 的数量)
  • 上面的条件都满足,就证明 p 有两种模式,这就需要我们获取字符 a 代表的子串的长度,较为简便的方法是枚举 a 子串的长度,然后利用除法来得到 b 子串的长度,来优化掉二层循环;

这里需要注意一种情况:只用 b 或只用 a 就能匹配完的情况

"bbbaa"
"xxxxxx"
预期:true
class Solution {
    int a, b;
    boolean isSingle(String v, int c) {	//单匹配模式
        int m = v.length();
        if (m % c != 0)
            return false;
        int k = m / c;   //每一个子串的长度
        String fir = v.substring(0, k);
        for (int i = k; i < m; i += k) {
            if (!fir.equals(v.substring(i, i+k)))
                return false;
        }
        return true;
    }
    boolean isDouble(String p, String v, int aLen, int bLen) {	//双匹配模式
        String s1 = null, s2 = null;
        for (int i = 0, j = 0; i < p.length(); i++) {
            if (p.charAt(i) == 'a') {
                if (s1 == null)
                    s1 = v.substring(j, j+aLen);
                else if (!s1.equals(v.substring(j, j+aLen)))
                    return false;
                j += aLen;
            } else {
                if (s2 == null)
                    s2 = v.substring(j, j+bLen);
                else if (!s2.equals(v.substring(j, j+bLen)))
                    return false;
                j += bLen;
            }
        }
        return true;
    }
    public boolean patternMatching(String p, String v) {
        int n = p.length(), m = v.length();
        if (n == 0)
            return m == 0;
        for (char c : p.toCharArray()) {
            if (c == 'a') a++;
            else          b++;
        }
        if (m == 0)                 // v为空,那么模式只能有一种:xxx
            return a == 0 || b == 0;
        if (a == 0) return isSingle(v, b);
        if (b == 0) return isSingle(v, a);
        
        if (isSingle(v, a) || isSingle(v, b))
            return true;
        for (int aLen = 1; aLen * a <= m - b; aLen++) { //枚举aLen,然后从aLen推导出bLen
            if ((m - aLen * a) % b == 0) {
                int bLen = (m - aLen * a) / b;
                if (isDouble(p, v, aLen, bLen))
                    return true;
            }
        }
        return false;
    }
}

复杂度分析

  • 时间复杂度: O ( n × m ) O(n × m)
  • 空间复杂度: O ( 1 ) O(1)

猜你喜欢

转载自blog.csdn.net/qq_43539599/article/details/106910982
今日推荐