最长回文串(可不连续)与最大公共子串(可不连续)

其实标题上的这两种情况转化一下就是一种情况,即最大公共子串(可不连续)。最长回文串(可不连续)的意思是以某个字符为轴,分别往左右遍历的公共子串的最大长度(可不连续),那么不如将最大回文串改为一个字符串的顺序与逆序的最大公共子串(可不连续)。以下通过一道题目进行解释。

题目描述:

回文串是指aba、abba、cccbccc、aaaa这种左右对称的字符串。每个字符串都可以通过向中间添加一些字符,使之变为回文字符串。
例如:abbc 添加2个字符可以变为 acbbca,也可以添加3个变为 abbcbba。方案1只需要添加2个字符,是所有方案中添加字符数量最少的。
Input
输入一个字符串Str,Str的长度 <= 1000。
Output
输出最少添加多少个字符可以使之变为回文字串。
Input示例
abbc
Output示例
2

思路解析:添加几个字符即删除几个字符,相当于在一个字符串找最大回文串可不连续,又因为回文串左右对称,所以只要求这个字符串的顺序和倒序的最大公共串(可不连续)的问题了。最大公共串的求解公式dp[i][j]= max(dp[i - 1][j - 1] + x,dp[i - 1][j], dp[i][j - 1])(i!=0 and j!=0),其中x是指0或者1,当s[i]=s[j]取1否则为0;dp[i][j]表示s1前i+1个与s2前j+1个的公共字符个数,最终添加的字符串个数就是字符串的长度与最大公共子串长度的差值。

代码实现:

# -*-coding:utf-8 -*-
def maxcommon(s1, s2):
    m = len(s1)
    n = len(s2)
    dp = [[0 for i in range(m)] for j in range(n)]
    for i in range(n):
        for j in range(m):
            if s1[i] == s2[j]:
                x=1
            else:x=0
            if i!=0 and j!=0:
                dp[i][j]= max(dp[i - 1][j - 1] + x,dp[i - 1][j], dp[i][j - 1])
            elif i!=0:
                dp[i][j]=max(dp[i-1][j],x)
            elif j!=0:
                dp[i][j]=max(dp[i][j-1],x)
            else:
                dp[i][j]=x
    return dp[n - 1][m - 1]
while True:
    try:
        s1 = raw_input()
        s2 = s1[::-1]
        ls = len(s1)
        res = maxcommon(s1, s2)
        ans = ls - res
        print ans
    except:
        break


你可能感兴趣的:(动态规划,动态规划)