一、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;
}
}
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,