题目
你有两个字符串,即pattern和value。 pattern字符串由字母"a"和"b"组成,用于描述字符串中的模式。例如,字符串"catcatgocatgo"匹配模式"aabab"(其中"cat"是"a",“go"是"b”),该字符串也匹配像"a"、"ab"和"b"这样的模式。但需注意"a"和"b"不能同时表示相同的字符串。编写一个方法判断value字符串是否匹配pattern字符串。
解题思路
简单的思路:设
l
v
l_v
lv为value的长度,
l
a
l_a
la为a对应模式的长度,
l
b
l_b
lb为b对应模式的长度,
c
o
u
n
t
a
count_a
counta为a对应模式的个数,
c
o
u
n
t
b
count_b
countb为b对应模式的个数。则有:
c
o
u
n
t
a
×
l
a
+
c
o
u
n
t
b
×
l
b
=
l
v
count_a \times l_a +count_b \times l_b = l_v
counta×la+countb×lb=lv
则在已知
c
o
u
n
t
a
count_a
counta时,以
l
a
l_a
la和
l
b
l_b
lb为未知量得到二元一次方程,并且
l
a
∈
[
0
,
l
v
c
o
u
n
t
a
+
1
)
l_a\in [0,\frac{l_v}{count_a}+1)
la∈[0,countalv+1)。
l
a
l_a
la处于这个区间以保证
l
b
l_b
lb大于等于0。接下来遍历
l
a
l_a
la,得到分割后的子串是否满足要求。
0.统计a,b个数
统计pattern中a,b的个数
count_a = sum(1 for item in pattern if item == "a")
count_b = len(pattern)-count_a
1.特判
- 若a的个数小于b的个数,调换a、b以保证a最少出现1次,继而枚举a
if count_a < count_b:
count_a, count_b = count_b, count_a
pattern = "".join("a" if item == "b" else "b" for item in pattern)
- 若value为空,则要求pattern 中要么为空,要么只有a,等价于b的个数为0
if not value: return count_b == 0
- 若pattern为空而value不为空,则无法匹配。
if not pattern and value: return False
2.对于pattern和value都不为空时,两重遍历
for len_a in range(len(value)//count_a + 1):#遍历a的可能长度
leftForb = len(value) - count_a * len_a#可能的b的总长度
#看当前的分法是否满足要求(len(b)为大于等于0的整数)
if (count_b == 0 and leftForb == 0) or (count_b != 0 and leftForb % count_b == 0):
len_b = 0 if count_b == 0 else leftForb // count_b
idx, Judge = 0, True
value_a, value_b = None, None
for ch in pattern:#对于确定a,b长度进行遍历模式
if ch == "a":#对模式a的判断
subChr = value[idx:idx+len_a]
if not value_a:
value_a = subChr
elif value_a != subChr:
Judge = False
break
idx += len_a
else:#对模式b的判断
subChr = value[idx:idx+len_b]
if not value_b:
value_b = subChr
elif value_b != subChr:
Judge = False
break
idx += len_b
if Judge and value_a != value_b:#找到满足的value_a,value_b且两者不相等,返回T
return True
代码
class Solution:
def patternMatching(self, pattern: str, value: str) -> bool:
#统计a、b的个数
count_a = sum(1 for item in pattern if item == "a")
count_b = len(pattern)-count_a
#若a的个数小于b的个数,调换a、b以保证a最少出现1次,继而枚举a
if count_a < count_b:
count_a, count_b = count_b, count_a
pattern = "".join("a" if item == "b" else "b" for item in pattern)
#若value为空,则要求pattern 中要么为空,要么只有a,等价于b的个数为0
if not value: return count_b == 0
#若pattern为空而value不为空,则无法匹配
if not pattern and value: return False
#对于pattern和value都不为空时,遍历
for len_a in range(len(value)//count_a + 1):
leftForb = len(value) - count_a * len_a#可能的b的总长度
#看当前的分法是否满足要求(len(b)为大于等于0的整数)
if (count_b == 0 and leftForb == 0) or (count_b != 0 and leftForb % count_b == 0):
len_b = 0 if count_b == 0 else leftForb // count_b
idx, Judge = 0, True
value_a, value_b = None, None
for ch in pattern:
if ch == "a":#对模式a的判断
subChr = value[idx:idx+len_a]
if not value_a:
value_a = subChr
elif value_a != subChr:
Judge = False
break
idx += len_a
else:#对模式b的判断
subChr = value[idx:idx+len_b]
if not value_b:
value_b = subChr
elif value_b != subChr:
Judge = False
break
idx += len_b
if Judge and value_a != value_b:#找到满足的value_a,value_b且两者不相等,返回T
return True
return False#遍历完都没找到,返回F