leetcode专题训练 30. Substring with Concatenation of All Words

1.最开始的想法,wa了。想的是把所有列表中单词全都替换#串,这样的话,再扫描替换后的字符串,这个字符串中只要有连着的符合#号个数的#串,就是题目中要找的子串。然后发现题目中给的第二个样例都过不了,因为这个方法会将第二个样例整个替换成#。

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        if len(words) == 0:
            return [];
        tmp_s = s;
        subs = "";
        
        replace_s = "";#替换word的#串
        wordl = len(words[0]);
        for i in range(wordl):
            replace_s += "#";
            
        for word in words:
            tmp_s = tmp_s.replace(word, replace_s);
            subs = subs + replace_s;
        #print (tmp_s);
        result = [];
        for it in re.finditer(subs, tmp_s):
            result.append(it.start());
        #print (tmp.start());
        return result;

2.后来的想法,参考了第3题中的思路
第三题解答链接:https://blog.csdn.net/Ema1997/article/details/92798234
然而这种解法没有考虑到words中有重复单词的情况,又WA了,好吧我还是去看题解吧,我尽力了。

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        if len(words) == 0:
            return []
        result = []
        l = len(s)
        wordl = len(words[0])
        word_num = len(words)
        dic = {} #单词上一次出现位置
        i = 0
        left = 0 #记录当前串开始索引
        while i + wordl <= l:
            #print (l)
            if i - left == word_num * wordl: #已经找到了匹配
                result.append(left)
                left += wordl
                #print('2 {}'.format(i))
            if s[i:i+wordl] in words: #当前单词是words中的
                if s[i:i+wordl] not in dic or dic[s[i:i+wordl]] < left: #从未出现过或者出现位置在left之前
                    dic[s[i:i+wordl]] = i
                    #print('1 {}'.format(i))
                else:
                    left = dic[s[i:i+wordl]] + wordl
                    #print('left {}'.format(left))
                    dic[s[i:i+wordl]] = i
                i += wordl
            else:
                i += 1
                left = i
                #print('3 {} {}'.format(i, left))
        return result

3.看了题解之后,学习到了python中一个特别有用的函数Counter,可以用来统计list中每个元素出现过多少次,并返回一个Counter类型的值,这个Counter类型的值还能与字典类型的值做比较,判断是否相同,比如以下这段代码:

a = [1,4,2,3,2,3,4,2]
from collections import Counter
print (Counter(a))
b = Counter(a)
dic = {2: 3, 3: 2, 4: 2, 1: 1}
print(b == dic)

输出如下:

Counter({2: 3, 3: 2, 4: 2, 1: 1})
True

在了解了这个函数之后,这道题就好做许多了。我这里参考的是题解中的解法二,具体讲解大家看这个链接就行了,此处不做赘述。

from collections import Counter
class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        if len(words) == 0:
            return []
        result = []
        l = len(s)
        wordl = len(words[0])
        word_num = len(words)
        count = Counter(words) #每个单词出现多少次
        count_now = {} #当前字符串单词出现次数
        i = 0
        left = 0 #记录当前串开始索引
        for i in range(wordl):
            left = i
            count_now = {}
            while (i + wordl <= l):
                word = s[i:i+wordl]
                if (word not in words): #情况1,当前单词不再单词列表中
                    i += wordl #跳到下一单词
                    left = i
                    count_now = {}
                    continue
                if (word not in count_now):
                    count_now[word] = 1
                else:
                    count_now[word] += 1
                while (count_now[word] > count[word]): #情况2,单词出现次数超过单词列表中次数
                    count_now[s[left:left+wordl]] -= 1
                    left += wordl
                if (count_now == count):#情况3,匹配成功
                    result.append(left)
                    count_now[s[left:left+wordl]] -= 1
                    left += wordl
                i += wordl
        
        return result

终于把这道题做完了~\(≧▽≦)/~,感动。

你可能感兴趣的:(leetcode专题训练 30. Substring with Concatenation of All Words)