問題描述:
給定一個字符串s,找出這樣一個子串:
1)該子串中的任意一個字符最多出現2次;
2)該子串不包含指定某個字符;
請你找出滿足該條件的最長子串的長度。
輸入描述
第一行為要求不包含的指定字符,為單個字符,取值范圍[0-9a-zA-Z]
第二行為字符串s,每個字符范圍[0-9a-zA-Z],長度范圍[1,10000]
輸出描述
一個整數,滿足條件的最長子串的長度;如果不存在滿足條件的子串,則返回0
D
ABC123
6
D
ABACA123D
7
解題思路:
限制條件:
- 不包含指定字符
- 子串中任意字符出現不超過兩次
遍歷原字符串的每一個子串,符合條件則更新最大長度,否則下一個,字符串最大長度為
子字符串由起始位置與結束位置確定,如何優化這個過程
優化:
- 先固定結束位置,也就是只一個for循環遍歷結束位置,用left維護起始位置;問題:每次left都會重頭開始檢查限制條件
- 用right維護結束位置,兩者均初始化為0;符合條件則right+1,否則left+1,處理至target字符時,將兩者更新為target索引+1
以示例2為例:
是否符合 | T | T | T | T | F | T | T | T | |
子串 | A | AB | ABA | ABAC | ABACA | BACA | BACA1 | …… | BACA123 |
left | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | |
right | 0 | 1 | 2 | 3 | 4 | 4 | 5 | 8 |
代碼實現:
僅left單指針:
tar = input()
s = input()
ans = 0
for i in range(len(s)):left = 0if s[i] != tar:while left < i:flag = Truefor j in range(left,i+1):if s[j] == tar or s[left:i+1].count(s[j]) > 2:flag = Falseleft += 1breakif flag:ans = max(ans,i-left+1)break
print(ans)
left、right雙指針:
tar = input()
s = input()
ans = 0
left,right = 0,0
while right < len(s):if s[right] != tar:if s[left:right+1].count(s[right]) > 2:#只用檢查新增的right位置left += 1#不符合條件,左指針右移else:right += 1#符合條件,右指針右移ans = max(ans,right-left)else:#更新至target字符下一個位置left,right = right+1,right+1
print(ans)