467.环绕字符串中唯一的子字符串

51 阅读1分钟

题目:

算法:

方法一:模拟+回溯
执行会超时

func findSubstringInWraproundString(p string) int {
	subStr := make(map[string]struct{})
	// 长度为1,
	// 大于一,
	n := len(p)
	list := make([]byte, 0)
	var dfs func(i int)
	dfs = func(i int) {
		if i == n {
			return
		}
		dfs(i + 1)
		// 是否可以组成有效子串
		if len(list) > 0 {
			last := list[len(list) - 1] 
			if last + 1 != p[i] && p[i] + 25 != last {
				// fmt.Println(string(last), string(p[i]))
				return
			}  
		}
		
		list = append(list, p[i])
		subStr[string(list)] = struct{}{}
		dfs(i + 1)
		list = list[:len(list) - 1]
	}
	dfs(0)
	// fmt.Println(subStr)
	return len(subStr)
}

方法二:动态规划
dp[i] 表示以 p[i]为最后一个元素的子串长度。
如p="abc”,p[2] = 3, 三个子串分别是,"abc","bc","b"
最终结果为所有dp元素之和。
因为有了结尾元素p[i],和长度dp[i],我们可以据此去重
如dp['c']存在两个子串“abc”和“bc”,取最大值作为dp[i]的值即可实现去重

func findSubstringInWraproundString(p string) int {
	dp := make([]int, 26)
	k := 0
	for i := range p {
		if i > 0 && (p[i - 1] + 1 == p[i] || p[i] + 25 == p[i - 1]) {
			k ++
		} else {
			k = 1
		}
		dp[p[i] - 'a'] = max(dp[p[i] - 'a'], k)
	}
	ans := 0 
	for i := range dp {
		ans = ans + dp[i]
	}
	return ans
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}