识别字符串 [Python3]

识别字符串 [Python3]

识别字符串 是 LintCode(详见 LintCode介绍)所提供的一道 简单 级别的面试题,现在我对Python3的实现做以简单分析,如有不妥之处,欢迎指正。

题目描述

给定一组n个仅包含小写字母的字符串,为每个字符串找出能够唯一识别该字符串的最小前缀
即可以识别A串的最小前缀Ap,不会是其他n-1个字符串的前缀。
1 <= n <= 500;
字符串长度不超过100;
如果一个字符串S是另一个字符串T的前缀,则S的最小可识别前缀为S。

样例

看完题目描述有没有感觉比较绕?看个样例就可以了:

输入:[“aaa”,“bbc”,“bcd”]

输出:[“a”,“bb”,“bc”]

解释:“a"仅是"aaa” 的前缀;
"bb"仅是"bbc"的前缀;
"bc"仅是"bcd"的前缀;

即我们需要的是找到属于每个字符串所特有的最短前缀,要求该前缀不会在其他字符串中重复出现,如样例中所给出的"bbb" 以及"bcd":由于"b"在两者中均出现,所以不能直接取"b"作为符合要求的最短前缀。继续往后读,前者读到"bb"而后者读到"bc"出现不同前缀(即独有前缀)便可以作为符合要求的前缀,输出即可。

代码实现[Python3]

class Solution:
    def ShortPerfix(self, stringArray):
        if not stringArray:
            return []
        prefix = {
     }
        for string in stringArray:
            for idx in range(len(string)):
                prefix[string[:idx + 1]] = prefix.get(string[:idx + 1], 0) + 1
        res = []
        for string in stringArray:
            for idx in range(len(string)):
                if prefix[string[:idx + 1]] == 1:
                    res.append(string[:idx + 1])
                    break
                if idx == len(string) - 1:
                    res.append(string)
        return res

第一行定义类Solution(解决方案)这是LintCode所要求的部分,只是为了顺利进行代码测试,不必要过多阐述。
主要功能在于函数ShortPerfix,其带有一个参数stringArray(self是作为有class前提的必要参数,之后代码并没有调用,所以这里不再讲解)。参数stringArray 是一个输入的字符串数组,也就是我们将进行前缀识别的字符串数组。

函数首先执行了一个简单判断句 if not stringArray 考虑了空字符串的情况,若输入空,则返回空。随后定义一个perfix来存储可能得到的前缀长度。string[:idx + 1] 表示截取字符串string从起始位置到索引为 idx + 1 位置的字符串。

接下来,利用for循环遍历输入数组中所有字符串,然后根据每个字符串的长度(len(string))获取其可能存在的最短前缀长度。
下一步进行前缀判断,使用了2个if来判断不同情况,第一个:若所得前缀在idx + 1处长度为1,则将此前缀加入res(即最终输出的数组)中。第二个:若此时索引值为字符串长度减一(即前缀为整个字符串),则直接把字符串加入res中。

最终输出所得 res 结果。

更好的方案

在刚才的分析中,细心的朋友们就会发现,在整个程序中执行了两次字符串数组遍历,且把获取前缀和判断前缀分成了两部分,这样的写法确实通俗易懂,但使得程序运行的时间达不到最快(LintCode上该代码测试平均耗时 302 ms ,这已经很快了)。

以下是一个极好的解决方案(仅 201 ms):

class Solution:
    def ShortPerfix(self, stringArray):
        from collections import defaultdict
        Trie = lambda: defaultdict(Trie)
        root = Trie()
        for string in stringArray:
            p = root
            for c in string:
                p = p[c]
                if '#' not in p:
                    p['#'] = 0
                p['#'] += 1
            p['$'] = True
        
        ans = []
        for string in stringArray:
            p = root
            cur = ""
            for c in string:
                p = p[c]
                cur += c
                if p['#'] == 1:
                    ans.append(cur)
                    break
            else:
                ans.append(string)
        return ans

这个写法就很高级,高级到我看不懂,它好像是直接在collections中引入一种缺省类实例化然后进行一顿十分高级的操作就完成了判断,这段代码真的看得头晕眼乏,希望有大佬讲解一下。

感谢浏览(点个赞再走呗)

你可能感兴趣的:(字符串,python,算法)