一、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;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,