你有两个字符串,即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仅包含小写字母。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/pattern-matching-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解:
- 当pattern为空的情况,如果value也等于空,返回true,否则false
- 当pattern不为空的情况
2.1 如果value为空,判断pattern是否只有一种元素,如果是true,否则false。
2.2 如果value不为空,分别得到pattern中a和b的个数
2.2.1 如果a,b中有一个为0,则判断value能否被a或者b的个数平分,并判断每块的字符是否都相等。
2.2.2 如果a,b都不为0,那么判断如果只使用一个进行匹配a或者b,令另一个匹配空字符,进行2.2.1相同的判断。
2.2.3 如果2.2.2不成功,那么我们进行枚举匹配。依据公式a*len_a + (n-a)len_b = m。
len_a: a匹配的字符的长度
len_b: b匹配的字符的长度
a:表示pattern中a的个数
b:表示pattern中b的个数
n:pattern的长度
m:value的长度
依据公式推出len_a和len_b,然后在value中进行匹配,匹配成功true,不成功false。
package QuestionDays.June;
public class day22patternMatching {
public static void main(String[] args) {
//此题主要解法是将待匹配字符根据ab分成几块,主要是确定ab分别对应的字符个数,然后进行匹配
//ca*a + (n-ca)*b = all
//需要处理当patt,value为空的情况
//当pattern为空时,如果value也为空 true
//当pattern不为空时,如果value为空 ,判断pattern是否只由一个字符组成
//当pattern不为空,value也不为空时,先处理a,b的个数,如何枚举匹配
String pattern = "aaaaab";
String value = "xahnxdxyaahnxdxyaahnxdxyaahnxdxyaauxuhuo";
System.out.println(patternMatching(pattern, value));
}
public static boolean patternMatching(String pattern, String value) {
//1.pattern为空
if (pattern.length() == 0) return value.length() == 0;
//2.pattern不为空时
//2.1value为空时,判断pattern是否为一个字母组成
char[] c = pattern.toCharArray();
int n = pattern.length();
if (value.length() == 0) {
int v = 0;
for (int i = 1; i < n; i++) {
if (c[i] == c[0]) {
v++;
}
}
if (v == n - 1) {
return true;
}else return false;
}
//2.2当pattern和value都不为空时,办正事
//(1)统计a,b的个数
int[] cnt = new int[2];
for (int i = 0; i < n; i++) {
cnt[c[i] - 'a']++;
}
//(2)判断cnt[0],cnt[1]是否有为0的情况
if (cnt[0] == 0) return helper(value, cnt[1]);
if (cnt[1] == 0) return helper(value, cnt[0]);
//2.2.1假设使得a,b其中之一为空,即次数为0
if (helper(value, cnt[0])) return true;
else if (helper(value, cnt[1])) return true;
//2.2.2 a,b都不为空,枚举a,b匹配的长度,使得a*len_a + b*len_b = len_value
int m = value.length();
for (int len_a = 1; len_a * cnt[0] <= m - cnt[1]; len_a++) {
if ((m - len_a * cnt[0]) % cnt[1] != 0) continue;
int len_b = (m - len_a * cnt[0]) / cnt[1];
if (check(pattern, value, len_a, len_b)) return true;
}
return false;
}
//pattern不为空,value不为空,判断是否可以k次切分value
public static boolean helper(String value, int k) {
int m = value.length();
if(m % k != 0) return false;
int len = m / k;
for(int i = len; i < m; i+= len) {
if(!value.substring(i, i + len).equals(value.substring(0,len))) return false;
}
return true;
}
public static boolean check(String pattern, String value, int len_a, int len_b) {
String[] ps = { "", ""};
boolean correct = true;
char[] c = pattern.toCharArray();
for(int i = 0, j = 0; i < pattern.length(); i++) {
//i,j指针都是恰当长度的
if(c[i] == 'a') {
if(ps[0].length() == 0) {
ps[0] = value.substring(j, j + len_a);
} else if(!value.substring(j, j + len_a).equals(ps[0])) {
correct = false;
break;
}
j += len_a;
}else if(c[i] == 'b') {
if(ps[1].length() == 0) ps[1] = value.substring(j, j + len_b);
else if(!value.substring(j, j + len_b).equals(ps[1])) {
correct = false;
break;
}
j += len_b;
}
}
if(correct && !ps[0].equals(ps[1])) return true;
return false;
}
}