【字符串】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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章