• 算法36---字符串匹配算法


    一、题目:赎金信(一个字符串字母是不是都在另一个字符串中)

    给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成。如果可以构成,返回 true ;否则返回 false。

    (题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。)

    注意:

    你可以假设两个字符串均只含有小写字母。

    canConstruct("a", "b") -> false
    canConstruct("aa", "ab") -> false
    canConstruct("aa", "aab") -> true

    思路:

    ①删

    ②set+count

    代码:

        def canConstruct(self, ransomNote, magazine):
            """
            :type ransomNote: str
            :type magazine: str
            :rtype: bool
            """
            '''
    
    #删
            b= list(magazine)
            for aa in ransomNote:
                if aa not in b:
                    return False
                b.remove(aa)
            return True
            '''
    #set + count
            a = set(ransomNote)
    
            for aa in a:
                if ransomNote.count(aa) > magazine.count(aa):
                    return False
            return True    

    二、题目:正则化表达式匹配【含通配符】

    给定一个正则字符串p,一个字符串s。要求验证s和p是否能匹配。

    特别的,正则字符串中仅由两个特殊字符:'.'表示任意的单个字符,'*'表示其前方紧邻元素连续出现0个或者更多个。要求匹配需要覆盖整个输入字符串,而不是部分的匹配。

    s 可能为空,且只包含从 a-z 的小写字母。
    p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。

    Some examples: isMatch("aa","a") → false
    isMatch("aa","aa") → true
    isMatch("aaa","aa") → false
    isMatch("aa", "a*") → true
    isMatch("aa", ".*") → true
    isMatch("ab", ".*") → true
    isMatch("aab", "c*a*b") → true

    思路:动态规划:

    状态转移数组 f [i] [j] 表示利用 p 的前 i 个字符匹配 s 的前 j 个字符的匹配结果(成功为true,失败为false)。

    边界:

    • dp[0][0] = True,s和p都是空格。
    • i = 0,只有p为这种情况 p = ‘a*b*c*'才能True,别的都为False。

            for i in range(1,len(p)+1):           

    if p[i-1] == '*': if i >= 2:

    dp[0][i] = dp[0][i-2]

    • j = 0,全部为False。即p为空,都False。

    非边界:

    如果s[i] == p[j] 或者 p[j] == '.':【如果s的最后一位和p的最后一位相同,则只需要判断前面的】

    dp[i][j] = dp[i - 1][j - 1]

    如果p[j] == '*':【dp[i][j-2]:*前面一位为0个即可,Sx~P】【dp[i][j-1]:*前面一位为1个,Sx~Pz】【dp[i-1][j]:*匹配x(x==z或者z=='.'), S~Pzy】

      dp[i][j] = dp[i][j-2] || dp[i][j-1] || (dp[i-1][j] and (s[i-1]==p[j-2] or p[j-2]=='.'))

    解释:

    对于s和p,设各个最后一个字符为x, y,p的倒数第二字符为z,除此外前面字符设为S,P,则:

    s = Sx

    p = Pzy

    • 如果x == y或y == '.',则如果S和Pz匹配,则s和p匹配,因为最后两字字母是匹配的。这就缩减了问题规模。
    • 而对于y ==  '*'的情况,需要考虑z:

        如果x != z,则只有在s和P匹配的情况下,s和p才匹配。

        如果x == z,设匹配符号为~吧,方便,则如果S~PzySx~PSx~Pz,【S~P,S~Pz也匹配】都可得出s和p匹配。

     代码:

        def isMatch(self, s, p):
            """
            :type s: str
            :type p: str
            :rtype: bool
            """
            dp = [[False] * (len(p) + 1) for i in range(len(s) + 1)]
            dp[0][0] = True
    
            for i in range(1,len(p)+1):
                if p[i-1] == '*':
                    if i >= 2:
                        dp[0][i] = dp[0][i-2]
            for i in range(1,len(s)+1):
                for j in range(1,len(p)+1):
                    if p[j-1]=='.' or s[i-1] == p[j-1]:
                        dp[i][j] = dp[i-1][j-1]
                    elif p[j-1]=='*':
                        dp[i][j] = dp[i][j-2] or dp[i][j-1] or (dp[i-1][j] and (s[i-1]==p[j-2] or p[j-2]=='.'))
        return dp[len(s)][len(p)]

     

    三、题目:字符串匹配

    有一个字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符串"ABCDABD"?如果匹配则返回True,否则FALSE。

    思路:KMP、Rabin-Karp、

    https://blog.csdn.net/airfer/article/details/8951802/

    https://blog.csdn.net/a345017062/article/details/52452667

    
    
  • 相关阅读:
    关于 继承、扩展和协议,深度好文
    BearSkill纯代码搭建iOS界面
    漫谈程序猿系列:程序猿零门槛?
    Uva--11324--The Largest Clique【有向图强连通分量】
    iOS_UITextField 基本操作
    苹果官方xcodeprojectbuild设置指南
    <html>
    Matlab 随机数字
    基于中文人员特征的性别判定方法
    小米用户画像的演进及应用解读
  • 原文地址:https://www.cnblogs.com/Lee-yl/p/9660557.html
Copyright © 2020-2023  润新知