目录
字符串距离
思路整理
完整代码
字符串提取
思路自记
计算重复字符串长度
思路自记
字符串连连看
思路自记
字符串匹配
思路自记
完整代码
字符串类笔试题总结
字符串距离
给出两个相同长度的由字符 a 和 b 构成的字符串,定义它们的距离为对应位置不同的字符 的数量。如串”aab”与串”aba”的距离为 2;串”ba”与串”aa”的距离为 1;串”baa”和串”baa”的 距离为 0。下面给出两个字符串 S 与 T,其中 S 的长度不小于 T 的长度。我们用|S|代表 S 的 长度,|T|代表 T 的长度,那么在 S 中一共有|S|-|T|+1 个与 T 长度相同的子串,现在你需要计 算 T 串与这些|S|-|T|+1 个子串的距离的和。
思路整理
首先理解完这个题目之后,感觉还是很简单的,想到的思路就是,我把S字符串每一动一个字符,就切出一个长度为T的子字符串,再拿这个子字符串跟T字符串计算距离,再把距离累加,很快,就能得出结果了。
S = raw_input().split()
T = raw_input().split()
num = 0
s = len(S[0])
t = len(T[0])
if s == t:
for x,y in zip(S[0],T[0]):
if x != y:
num += 1
else:
for i in range(s-t+1):
for x,y in zip(S[0][i:(i+t)],T[0]):
if x != y:
num+=1
print num
但一弄完就掉坑里面了,按这么普通的思路,一下子就导致超出时间了。
所以,得换个思路,但怎么都没办法把时间给缩小,没辙之后,看牛客大神的做法,发现,还是人家的脑子好使啊!
思路如下:人家的境界没我这么low,上来就直接切,而是用数字的方式代替,首先,构造一个长度比S大1的的新列表,初始元素为0,从第二位起,计算出现过的'a'的个数,出现'a'就加一,出现‘b’就维持上一个元素的值进行填充。
temp = [0]
for i in range(len(arr1)):
if arr1[i] == 'a':
temp.append(temp[-1] + 1)
else:
temp.append(temp[-1])
这样,就构造好了一个新列表,接下来就开始对T开始遍历:
再反复的琢磨后,总算是读懂了人家的思路,刚才所建立的新列表,实际上是保留了a的个数信息,下面开始对T中的每个元素进行遍历,如果当前元素是‘b’,那么就拿新序列中取跟T等长的段中出现的a的次数,因为当前比较元素是‘b’,所以,当a出现几次,就意味着距离是几;同理,如过当前元素是‘a’,那么拿这个段的长度减去a出现所占的次数,就是b出现的次数了,也就是距离了。依次类推,不断遍历,最终就把距离累加出来了。
PS:这里的delta估计并不是指一个S中有多少个T,而是指两个字串之间对应字符的间隔。
delta = len(arr1) - len(arr2) + 1
res = 0
for i in range(len(arr2)):
if arr2[i] == 'b':
res += temp[i + delta] - temp[i]
else:
res += delta - (temp[i + delta] - temp[i])
反思,每写一道题会耗费很长时间,要是不总结清楚就太可惜了。反观这道题,利用字符串只包含ab两种字符的特点来设计,而且,拿第二个字符串跟他进行遍历,小串比大串。
完整代码
def get_count(arr1, arr2):
temp = [0]
for i in range(len(arr1)):
if arr1[i] == 'a':
temp.append(temp[-1]+1)
else:
temp.append(temp[-1])
delta = len(arr1) - len(arr2) + 1
res = 0
for i in range(len(arr2)):
if arr2[i] == 'b':
res += temp[i+delta] - temp[i]
else:
res += delta - (temp[i+delta] - temp[i])
return res
if __name__=='__main__':
arr1 = raw_input()
arr2 = raw_input()
print get_count(arr1, arr2)
字符串提取
请从字符串中提取以最后一个[img]开头、以最后一个[\img]结尾的字符串,未找到匹配的字符串返回"null"
思路自记
此题比较简单,直接一次遍历再加上两个判断就可以实现。这个需要警记的只需要一个,就是[img]的索引要比[\img]小才行,否则是要返回null的。
def get(arr):
index1 = 0
index2 = 0
if '[img]' not in arr or '[\img]' not in arr:
return 'null'
else:
for i in range(len(arr)):
if arr[i:i+5] == '[img]':
index1=max(i,index1)
elif arr[i:i+6] == '[\img]':
index2 = max(i, index2)
if index1 < index2:
return arr[index1:index2+6]
else:
return 'null'
arr = raw_input()
print get(arr)
计算重复字符串长度
请从字符串中找出至少重复一次的子字符串的最大长度
思路自记
PS:我本来觉得会很难,因为我隐隐约约记得好像有个叫求最长公共字串题目,但我当时没做出来,因为我能想到的就只有遍历了,但害怕超时,就直接翻看答案了,结果,,, 真tm就是直接遍历就行了!!!!
用两个循环i,j,i当作开头,j当作结尾,然后开始让j循环一遍,记录下来,如果有重复的设置一个计数器加一,再更改i,然后再循环一遍j,然后设置一个最大值,始终记录计数器的最大值。就可以了。
arr = raw_input().strip()
s = len(arr)
ss = 0
for i in range(s):
num = 0
for j in range(i+1, len(arr)):
if arr.count(arr[i:j]) > 1:
s = len(arr[i:j])
if s > ss:
ss = s
print ss
PS:中间纠结了一番,把最大长度看成了,最大次数,看来逻辑缜密能力还有待提高。
字符串连连看
对于输入的字符串,从左到右扫描字符串,如果存在由三个以上(包括三个)连续相同字符组成的子串,就将这个子串从原串中去掉,并将原有字符串剩下的部分拼接到一起。重复上述过程,直到无法去掉任何子串。
思路自记
理解完题意之后就觉得很简单,马上开始编程,本着,找三连续的思想,开始,很快就写出来了:
arr = raw_input().strip()
arr = list(arr)
new_index = []
for i in range(len(arr)-4):
if arr[i] == arr[i+1] and arr[i+1] == arr[i+2]:
new_index.append(i)
new_index.append(i+1)
new_index.append(i+2)
if arr[i] == arr[i+4] and arr[i+4] == arr[i+5]:
new_index.append(i)
new_index.append(i+4)
new_index.append(i+5)
if arr[i] == arr[i+1] and arr[i+1] == arr[i+4]:
new_index.append(i)
new_index.append(i+1)
new_index.append(i+4)
new_index.reverse()
for x in new_index:
del[arr[x]]
new_index = []
print ''.join(arr)
但本着看着越容易,坑越多的经验,还是写错了,为啥呢?人家要求 是不断重复,直到无法去掉任何子串,但我的思路是只进行一次,而且,无法控制循环的数量,经过一次后,的确能把当前序列的三连续给去掉,但去掉之后剩下的竟然又能重新组成三连续。
又是琢磨了很久,看了看人家的,才恍然大悟,原来应该是动态的去调整啊!就设置一个temp去存放不重复的元素,然后,每一次跟这个比,重复了就用pop跳出,这个思路真妙!
arr = raw_input().strip()
arr = list(arr)
temp = []
for x in arr:
if len(temp) <= 1:
temp.append(x)
else:
if temp[-1] == x and temp[-2] == x:
temp.pop()
temp.pop()
else:
temp.append(x)
print ''.join(temp)
字符串匹配
牛牛有两个字符串A和B,其中A串是一个01串,B串中除了可能有0和1,还可能有'?',B中的'?'可以确定为0或者1。 寻找一个字符串T是否在字符串S中出现的过程,称为字符串匹配。牛牛现在考虑所有可能的字符串B,有多少种可以在字符串A中完成匹配。
例如:A = "00010001", B = "??"
字符串B可能的字符串是"00","01","10","11",只有"11"没有出现在字符串A中,所以输出3
思路自记
这个思路刚开始我没想出来,看了人家的思路,解清迷惑,先判断两个字符串的长度如果B的字符串长度大于A,那么这个问题就没意义了,接着,初始化为零一个计数器,再设置一个空列表。
if len(B)>len(A):
return 0
length_B = len(B)
count = 0
res = []
接着,开始遍历,(len(A)-len(B)+1:表示B中有多少个A),从0开始遍历,首先判断A中一个与B字符串等长的字符串,来跟B来比较,这两个字符串逐个字符比较,如果B中的字符为‘?’,或者与对应的子串的对应字符相等,就计数器temp加1,最后,如果这两个字符串相等可以匹配,那么tmp肯定是等于B的长度的(因为每个字符都可加1)。那么,如果相对,就把这个从A中找出的字串,保存在res中。最后,读取出来就行。
for i in range(len(A) - length_B + 1):
tmp = 0
for j in range(length_B):
if B[j] == '?' or B[j] == A[i:i+length_B][j]:
tmp += 1
if tmp == length_B:
res.append(A[i:i+length_B])
else:
break
完整代码
def solution(A,B):
if len(B)>len(A):
return 0
length_B = len(B)
count = 0
res = []
for i in range(len(A) - length_B + 1):
tmp = 0
for j in range(length_B):
if B[j] == '?' or B[j] == A[i:i+length_B][j]:
tmp += 1
if tmp == length_B:
res.append(A[i:i+length_B])
else:
break
return len(set(res))
if __name__=='__main__':
A = raw_input().strip()
B = raw_input().strip()
print solution(A,B)