算法67-----环绕字符串中唯一的子字符串【动态规划】

一、题目:

把字符串 s 看作是“abcdefghijklmnopqrstuvwxyz”的无限环绕字符串,所以 s 看起来是这样的:”…zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd….”. 

现在我们有了另一个字符串 p 。你需要的是找出 s 中有多少个唯一的 p 的非空子串,尤其是当你的输入是字符串 p ,你需要输出字符串 sp 的不同的非空子串的数目。 

注意: p 仅由小写的英文字母组成,p 的大小可能超过 10000。

 

示例 1:

输入: "a"
输出: 1
解释: 字符串 S 中只有一个"a"子字符。

 

示例 2:

输入: "cac"
输出: 2
解释: 字符串 S 中的字符串“cac”只有两个子串“a”、“c”。.

 

示例 3:

输入: "zab"
输出: 6
解释: 在字符串 S 中有六个子串“z”、“a”、“b”、“za”、“ab”、“zab”。.

思路:动态规划:时间O(n),空间O(1)

http://www.cnblogs.com/grandyang/p/6143071.html

dp【i】表示以26个字母中第i个字母作为结尾的连续子串个数。dp[0] 表示以a为结尾的,dp[1]表示以b为结尾的……。

我们看abcd这个字符串,

以a为结尾的子字符串为a,dp[0] = 1

以b为结尾的子字符串为b,ab 。dp[1] = 2

以c为结尾的子字符串为c,bc,abc。dp[2] = 3

以d结尾的子字符串有abcd, bcd, cd, d,故 i = 3,dp[3] = 4。

结果为:1+2+3+4 = 10

题目可以转换为分别求出以每个字符(a-z为结束字符的最长连续字符串就行了,我们用一个数组res记录下来,最后在求出数组res的所有数字之和就是结果。

代码:

def findSubstringInWraproundString(p):
    if not p:
        return 0
    n = len(p)
    m = 0
    dp = [0] * 26
    for i in range(n):
            # if dp[i+1][j] == 1 and dp[i][j-1] == 1:
        if i > 0 and (ord(p[i]) - ord(p[i-1]) == 1 or ord(p[i]) - ord(p[i-1]) == -25): 
            m += 1 
        else:
            m = 1
        dp[ord(p[i]) - 97] = max(dp[ord(p[i]) - 97] ,m)
    res = sum(dp)
    return res
p = "zabbyz"
findSubstringInWraproundString(p)

 

点赞