leetcode 30 Substring with Concatenation of All Words

Substring with Concatenation of All Words

You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters.

For example, given:
S"barfoothefoobarman"
L["foo", "bar"]

You should return the indices: [0,9].
(order does not matter).

L中的每个单词长度都相等,这句话很奇怪。从这个单词长度入手,每次从S中取出一个单词长度,检查L中是否存在,存在就删除,直至L为空,就可以判断。当然,每次L需要deepcopy使用。

每次deepcopy,当S太长时比如7000个时会超时,因此加入needcopy判断:只有从中删除过才需要重新copy。时间从1.9s降到0.1s。

class Solution:
    # @param S, a string
    # @param L, a list of string
    # @return a list of integer
    def findSubstring(self, S, L):
        from copy import deepcopy
        if S=="" or L==[]:
            return []
        l=len(L[0])
        sl=len(S)
        ans=[]
        needcopy=True
        for i in range(sl-l):
            start=i
            if needcopy:
                dic=deepcopy(L)
                needcopy=False
            while dic:
                tmp=S[start:start+l]
                if tmp in dic:
                    dic.remove(tmp)
                    needcopy=True
                    start+=l
                else:
                    break
            if dic==[]:
                ans.append(i)
        return ans

当S="a'*5000, L=["a" * 5001]时,超时。加上条件

len(L)>len(S) or len(L)*len(L[0])>len(S)
即可通过。

但是S="ab"*5000, L=["ab","ba"]*250时,仍然超时。。本地运行需要2s+

优化还得从S入手。比如abababab...,每次判断的的子串都是abab...,因此可以加入一个字典hasProcessed={},重复的子串就不需要每次判断了。

    toProcess=S[start:start+ll]
    if toProcess in hasProcessed:
        continue

并在没匹配成功时

hasProcessed[toProcess]=True

本机上0.27s即通过。 但是提交的时候:   Memory Limit Exceeded -_-|||...
把字典换为列表,可以节省内存,但是速度大大降低。。

好吧,,再修改一下,把toProcess先hash()一下,再存到字典里,就不会超内存了。

AC代码如下

<pre name="code" class="python">class Solution:
    # @param S, a string
    # @param L, a list of string
    # @return a list of integer
    def findSubstring(self, S, L):
        from copy import deepcopy
        if S=="" or L==[] or len(L)*len(L[0])>len(S):
            return []
        l=len(L[0])
        sl=len(S)
        ll=l*len(L)
        ans=[]
        needcopy=True
        hasProcessed={}
        for i in range(sl-l<span style="color:#ff0000;">+1</span>):
            start=i
            toProcess=S[start:start+ll]
            if hash(toProcess) in hasProcessed:
                continue
            # else:<span style="color:#ff0000;"> 注意位置,应该在匹配不成功时才加入字典!</span>
            #     hasProcessed[hash(toProcess)]=True
            if needcopy:
                dic=deepcopy(L)
                needcopy=False
            while dic:
                tmp=S[start:start+l]
                if tmp in dic:
                    dic.remove(tmp)
                    needcopy=True
                    start+=l
                else:
                    hasProcessed[hash(toProcess)]=True
                    break
            if dic==[]:
                ans.append(i)
        return ans


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值