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]
    
  • 相关阅读:
    用C++发邮件
    python打包程序py2exe实战
    分享:Python: 数据分析资源
    Socket传输文件时进行校验(简单解决TCP粘包问题)
    第二回 基类的架造方法应该为子类想的多一些
    第一回 要想知道为什么抽象出基类,应该先对基类有一个比较明确的认识
    树型结构~无限级联下拉列表框
    为什么我要将数据库上下文进行抽象,为它生产一个基类有用吗~目录
    将不确定变为确定~真的是SqlDataReader引起的超时?
    张学友 《她来听我的演唱会》
  • 原文地址:https://www.cnblogs.com/YoungF/p/14296961.html
Copyright © 2011-2022 走看看