描述:查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。
注:子串的定义:将一个字符串删去前缀和后缀(也可以不删)形成的字符串。请和“子序列”的概念分开!
数据范围:字符串长度1\le length \le300 \1≤length≤300 进阶:时间复杂度:O(n^3)\O(n 3) ,空间复杂度:O(n)\O(n)
输入描述:输入两个字符串
输出描述:返回重复出现的字符
输入:
abcdefghijklmnop
abcsafjklmnopqrstuvw
输出:
jklmnop
# 1/input-str-stra-strb-strip
# 2/def-stra-forirange-stra[i:]遍历从前往后
# 3/def-stra-遍历从后往前依次少1个元素
# 4/特殊情况ainbORbina则直接打印子串
# 111222abc333444555
# 555123cccabc567890
# 样例数据里面最短串时要判断长度才行
# 下面字符串看起来上面的长,但实际上是下面的长,所以只需要判断其中一个即可要么tempa,要么tempb
# 此处绕了个弯路,以为是取所有两个串里面,最先出现的那个串,所以用了 三个值元组(值,长度,遍历元素对应的索引)
# nvlrzqcjltmrejybjeshffenvkeqtbsnlocoyaokdpuxutrsmcmoearsgttgyyucgzgcnurfbubgvbwpyslaeykqhaaveqxijc
# wkigrnngxehuiwxrextitnmjykimyhcbxildpnmrfgcnevjyvwzwuzrwvlomnlogbptornsybimbtnyhlmfecscmojrxekqmj
def exam(stra,strb):
lena,lenb = len(stra),len(strb)
if stra in strb:
return stra
if strb in stra:
return strb
length = 0
tempa = []
# 要求较短串,len(‘iiii’)在网页页面显示要比len-ooo可能要短,看起来短的实际len长问题
# 较短串则只需要查短串的即可,a小于b,则查a的子串
if lena < lenb:
# 每个字符开始,从当前位置选择1个长,2个长,3*,构建子串去判断是否在str内
for i in range(lena):
# 以i为锚点,进行遍历,取当前i0+1=1开始直到最后1个也就是len+1所有子串 i:j,判断
# 是否在长串strb里面,如果在,则该遍历的子串写入到tempa列表取
for j in range(i+1,lena+1):
# print(stra[i:j])
if stra[i:j] in strb:
tempa.append((stra[i:j],len(strb[i:j]),i))
# 左到右遍历即可,右到左遍历,会出现重复 无需要遍历
# if stra[j:-(i+1)] in strb :
# temp.append(stra[j:-(i+1)])
# 遇到不在strb的则直接跳过
else:
continue
# 此处分开来,主要是以为题目是查两个串里面,找到所有串的最小索引,没注意最短串的最小索引要求。。。
tempb = []
if lena >= lenb:
for i in range(lenb):
for j in range(i+1,lenb+1):
if strb[i:j] in stra:
tempb.append((strb[i:j],len(strb[i:j]),i))
else:
continue
# temp:{'', 'lmno', 'mn', 'klmn', 'lm', 'jklmnop', 'klmnop', 'c', 'jklmn', 'f', 'p', 'jkl', 'k', 'mnop', 'klmno', 'kl', 'j', 'klm', 'l', 'abc', 'jklmno', 'lmn', 'm', 'jk', 'mno', 'bc', 'b', 'n', 'a', 'lmnop', 'ab', 'nop', 'no', 'op', 'jklm', 'o'}
# print(tempb)
# [('1', 0), ('1', 1), ('1', 2), ('12', 2), ('2', 3), ('2', 4), ('2', 5), ('a', 6), ('ab', 6), ('abc', 6), ('b', 7), ('bc', 7), ('c', 8), ('3', 9), ('3', 10), ('3', 11), ('5', 15), ('55', 15), ('555', 15), ('5', 16), ('55', 16), ('5', 17)]
tempab = tempa + tempb
# print(tempab)
maxk = sorted(tempab,key = lambda x:x[1],reverse=True)
maxv = sorted(tempab,key = lambda x:x[1],reverse=True)[0][1]
# print(maxk,maxv)
# [('abc', 3, 6), ('555', 3, 15), ('555', 3, 0), ('abc', 3, 9)
# 查最大maxv值,也就是单个子串最长的那个长度是多少,长度相等的对应元组值1写入res列表
res = []
for i in range(len(maxk)):
if maxk[i][1] == maxv:
res.append(maxk[i])
# print(res)
# [('vh', 2, 12), ('nb', 2, 22), ('bx', 2, 23), ('vh', 2, 3), ('bx', 2, 24), ('nb', 2, 64)]
# 取所有res最长的字符串里面,倒序排列,按照索引index取结果,算所有字符串里面最早出现的字符串
# 但题目是取最短串的最先子串,回头来看,还是需要先确认所有子串/再确认最长的子串列表/最后取索引最开始的
resv = sorted(res,key=lambda x:x[2],reverse=False)
return resv[0][0]
# 不能用set 会随机异常出现 导致取不到最长子串的最先出现那个的问题
# for i in list(set(temp)):
# res.append((i,len(i)))
# print(res)
# res = sorted(res,key=lambda x:x[1])
# res:=== [('jklmnop', 7), ('jklmno', 6), ('klmnop', 6), ('klmno', 5), ('lmnop', 5), ('jklmn', 5), ('klmn', 4), ('jklm', 4), ('mnop', 4), ('lmno', 4), ('abc', 3), ('jkl', 3), ('klm', 3), ('mno', 3), ('lmn', 3), ('nop', 3), ('jk', 2), ('bc', 2), ('kl', 2), ('lm', 2), ('op', 2), ('ab', 2), ('no', 2), ('mn', 2), ('o', 1), ('m', 1), ('b', 1), ('l', 1), ('j', 1), ('f', 1), ('c', 1), ('a', 1), ('n', 1), ('p', 1), ('k', 1), ('', 0)]
# 以上reverse出现了应该取yi 而不应该取nf或fx情况 要求取最先出现的,再一次看错题,题目要求短的串最先出现的;。。。
# res:=== [('nf', 2), ('fx', 2), ('yi', 2), ('g', 1), ('y', 1), ('n', 1), ('o', 1), ('t', 1), ('d', 1), ('f', 1), ('e', 1), ('m', 1), ('x', 1), ('i', 1), ('', 0)]
# maxv = 0
# maxv可sorted后再取reverseFalse最前/后那个,sorted快速排序算法效率更高,比for循环
# for i in res:
# if i[1] > maxv:
# maxv = i[1]
# print(maxv)
stra = input().strip()
strb = input().strip()
res = exam(stra,strb)
print(res)