zoukankan      html  css  js  c++  java
  • 动态规划专题

    最大子数组

    这个题,初学之时,老师教我们用分治算法,分三路:在左边子数组、在右边子数组以及跨越中线,其实用动态规划已经很简单了,看状态转移方程就明白了:

    [dp[i] = egin{cases}arr[i], & quad i==0\ max{dp[i-1]+arr[i], arr[i]}, & quad otherwise end{cases} ]

    def maximum_subarr(arr):
        if not arr:
            return None
        dp = [0]*len(arr)
        dp[0] = arr[0]
        for i in range(1, len(arr)):
            dp[i] = max(dp[i-1]+arr[i], arr[i])
        return max(dp)
    

    编辑距离

    状态转移方程为:

    [dp[i][j] = egin{cases}dp[i-1][j-1], & quad s1[i] == s2[j]\ min{dp[i-1][j], dp[i][j-1], dp[i-1][j-1]}+1, & quad otherwise end{cases} ]

    注意边界的情况:i、j是从1开始的,0表示空字符串。

    def edit_distance(s1, s2):
        if len(s1) == 0:
            return len(s2)
        if len(s2) == 0:
            return len(s1)
    
        dp = [[0]*(len(s2) + 1) for _ in range(len(s1) + 1)]
        for i in range(len(s1)+1):
            for j in range(len(s2)+1):
                if i == 0:
                    dp[i][j] = j
                elif j == 0:
                    dp[i][j] = i
                else:
                    if s1[i-1] == s2[j-1]:
                        dp[i][j] = dp[i-1][j-1]
                    else:
                        dp[i][j] = min(min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1
    
        return dp[len(s1)][len(s2)]
    

    最长公共子串

    状态转移方程为:

    [dp[i][j] = egin{cases}dp[i-1][j-1]+1, & quad s1[i] == s2[j]\ 0, & quad otherwise end{cases} ]

    最终的答案是整个dp数组中的最大值。

    def longest_common_substring(s1, s2):
        if not s1 or not s2:
            return 0
    
        max_len = 0
        dp = [[0]*(len(s2)+1) for _ in range(len(s1)+1)]
        for i in range(1, len(s1)+1):
            for j in range(1, len(s2)+1):
                if s1[i-1] == s2[j-1]:
                    dp[i][j] = dp[i-1][j-1] + 1
                    if dp[i][j] > max_len:
                        max_len = dp[i][j]
                else:
                    dp[i][j] = 0
    
        return max_len
    

    最长公共子序列

    子序列可以不是连续的,所以,状态转移方程为:

    [dp[i][j] = egin{cases}dp[i-1][j-1]+1, & quad s1[i] == s2[j]\ max{dp[i-1][j], dp[i][j-1]}, & quad otherwise end{cases} ]

    def longest_common_subseq(s1, s2):
        if not s1 or not s2:
            return 0
        m = len(s1)
        n = len(s2)
        dp = [[0]*(n+1) for _ in range(m+1)]
        for i in range(1, m+1):
            for j in range(1, n+1):
                if s1[i-1] != s2[j-1]:
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1])
                else:
                    dp[i][j] = max(max(dp[i-1][j-1]+1, dp[i][j-1]), dp[i-1][j])
        return dp[m][n]
    
  • 相关阅读:
    哈夫曼树与哈夫曼编码
    HTML & CSS整理
    MYSQL整理
    数据库报告存档
    一些网络报错信息记录
    复活~
    你必须知道的Docker数据卷(Volume)
    Sql Prompt 10下载安装破解图文教程
    通过Logstash由SQLServer向Elasticsearch同步数据
    Linux(CentOS)配置Docker随宿主机自启,容器自启( --restart=always)
  • 原文地址:https://www.cnblogs.com/YoungF/p/14296961.html
Copyright © 2011-2022 走看看