最长重复子串 高频面试题 题解

题目:
就是说有一个字符串s,比如'banana',然后你要求出来它最长的重复子串是什么? 
那什么叫最长重复子串呢?
首先,它是子串,是连续的子串这无需多言。
重复就是说不止出现一次
最长就是最长的那个。
所以最长重复子串就是 ‘最长的那个’ ‘重复过的’ ‘连续子串’。
最后,如果没有重复子串,请输出空串:''

字符串长度是10^5数量级

样例:
input
'banana'

output
'ana'

input 
'abcd'

output
''

这道题在华为二面出现过,在美团二面出现过,因此本人想要对此作出解析。这道题我看LC上甚至有什么Rabin-Krap,真滴恐怖(见都没见过),所以还是学了一个简单的常见的解法,希望能够抛砖引玉。

常规解法很好想:就是遍历所有长度,然后每一个子串都检查一下是不是重复出现,这里遍历要耗时n,检查重复也要耗时n(哈希表),所以是O(n^2)

那么,有没有能够优化的地方呢? 这里其实很好想,根据字符串10^5量级,一般就是要nlogn的复杂度,所以会联想到logn的一些算法,比如二分查找。

我们仅优化'遍历',把遍历所有长度,变成二分查找所有长度,就可以达到目的。 在我们的主函数中二分,如果当前长度满足条件就暂时保存这个答案,贪心地继续寻找更长的答案直到结束二分,在check函数中结合哈希表判断是否重复过。

代码如下:

class Solution:
    def longestDupSubstring(self, s: str) -> str:
      
      def check(cur_len):
        cnt = Counter()
        for i in range(len(s)):
          if i+cur_len>len(s):break
          if s[i:i+cur_len] in cnt:
            return s[i:i+cur_len]
          else:cnt[s[i:i+cur_len]] = 1
        return ''

      left,right = 0,len(s)
      res = ''
      while left<right:
        mid = (left+right)//2
        cur = check(mid)
        if cur=='':right = mid
        else:
          if len(res)<len(cur):res = cur
          left = mid+1
      return res  

#华为##美团##晒一晒我的offer#
全部评论
check用set可能更好
点赞 回复 分享
发布于 2023-10-20 18:15 湖南

相关推荐

11-01 08:48
门头沟学院 C++
伤心的候选人在吵架:佬你不要的,能不能拿户口本证明过户给我。。球球了
点赞 评论 收藏
分享
一名愚蠢的人类:多少games小鬼留下了羡慕的泪水
投递荣耀等公司10个岗位
点赞 评论 收藏
分享
9 10 评论
分享
牛客网
牛客企业服务