【題目】*面試題 16.18. 模式匹配
你有兩個字符串,即pattern和value。 pattern字符串由字母"a"和"b"組成,用於描述字符串中的模式。例如,字符串"catcatgocatgo"匹配模式"aabab"(其中"cat"是"a",“go"是"b”),該字符串也匹配像"a"、"ab"和"b"這樣的模式。但需注意"a"和"b"不能同時表示相同的字符串。編寫一個方法判斷value字符串是否匹配pattern字符串。
示例 1:
輸入: pattern = "abba", value = "dogcatcatdog"
輸出: true
示例 2:
輸入: pattern = "abba", value = "dogcatcatfish"
輸出: false
示例 3:
輸入: pattern = "aaaa", value = "dogcatcatdog"
輸出: false
示例 4:
輸入: pattern = "abba", value = "dogdogdogdog"
輸出: true
解釋: "a"="dogdog",b="",反之也符合規則
提示:
0 <= len(pattern) <= 1000
0 <= len(value) <= 1000
你可以假設pattern只包含字母"a"和"b",value僅包含小寫字母。
【解題思路1】枚舉
- 先判斷爲空的極端條件;
- 然後開始記錄a和b的數量,以及第一個a和b的座標,根據座標可以很容易找到兩者不同長度時對應的字符串;
- 然後優先判斷a和b的數量爲1的情況;
- 最後開始整活,由二元一次方程可以構造a的長度和b長度的關係,所有隻要遍歷a的長度情況就行了。
class Solution {
public boolean patternMatching(String pattern, String value) {
int count_a = 0, count_b = 0;
for (char ch: pattern.toCharArray()) {
if (ch == 'a') {
++count_a;
} else {
++count_b;
}
}
if (count_a < count_b) {
int temp = count_a;
count_a = count_b;
count_b = temp;
char[] array = pattern.toCharArray();
for (int i = 0; i < array.length; i++) {
array[i] = array[i] == 'a' ? 'b' : 'a';
}
pattern = new String(array);
}
if (value.length() == 0) {
return count_b == 0;
}
if (pattern.length() == 0) {
return false;
}
for (int len_a = 0; count_a * len_a <= value.length(); ++len_a) {
int rest = value.length() - count_a * len_a;
if ((count_b == 0 && rest == 0) || (count_b != 0 && rest % count_b == 0)) {
int len_b = (count_b == 0 ? 0 : rest / count_b);
int pos = 0;
boolean correct = true;
String value_a = "", value_b = "";
for (char ch: pattern.toCharArray()) {
if (ch == 'a') {
String sub = value.substring(pos, pos + len_a);
if (value_a.length() == 0) {
value_a = sub;
} else if (!value_a.equals(sub)) {
correct = false;
break;
}
pos += len_a;
} else {
String sub = value.substring(pos, pos + len_b);
if (value_b.length() == 0) {
value_b = sub;
} else if (!value_b.equals(sub)) {
correct = false;
break;
}
pos += len_b;
}
}
if (correct && !value_a.equals(value_b)) {
return true;
}
}
}
return false;
}
}
class Solution {
public boolean patternMatching(String pattern, String value) {
int a = 0, b = 0; //統計a與b的個數
for(int i = 0; i < pattern.length(); ++i){
if(pattern.charAt(i) == 'a') a++;
else b++;
}
if(value.equals("")){//空串直接返回
if(a*b == 0) return true;
return false;//a與b對應的串不能同時爲空
}
if(pattern.equals("")) return false;
if(b == pattern.length()) a = b; //只有a或只有b,統一處理
if(a == pattern.length()){
if(value.length()%a != 0) return false;
int c = value.length()/a;
String s = value.substring(0, c);//平均按照長度c斷開匹配
for(int i = 0; i < a; ++i){
if(!s.equals(value.substring(c*i, c*(i + 1)))) return false;
}
return true;
}
List<List<Integer>> r = new ArrayList<>();//記錄所有整數解的a與b的串的長度
for(int i = 0; i <= value.length(); ++i){
int temp = value.length() - a*i;
if(temp < 0) break;
if(temp%b == 0){
List<Integer> res = new ArrayList<>();
res.add(i);
res.add(temp/b);
r.add(res);
}
}
int i = pattern.indexOf('a'), j = pattern.indexOf('b');
for(List<Integer> v : r){
int m = v.get(0), n = v.get(1), sum = 0; //用sum累計下標值
String s1 = value.substring(i*n, i*n + m), s2 = value.substring(j*m, j*m + n);
if(s1.equals(s2)) continue; //a與b對應的串不能相等
boolean flag = true;
for(int k = 0; k < pattern.length(); ++k){
String s = pattern.charAt(k) == 'a'? s1: s2;
int p = pattern.charAt(k) == 'a'? m: n;
if(!s.equals(value.substring(sum, sum + p))){
flag = false;
break;
}
sum += p;
}
if(flag) return true; //只要存在一組解,就爲真
}
return false;
}
}