Lintcode 738.Count Different Palindromic Subsequences go

/**
738 · 计数回文子序列
算法
Hard
Accepted Rate
34%

DescriptionSolutionNotesDiscussLeaderboard
Description
给出一个字符串 S, 计算字符串 S 中不同非空回文子序列的数量, 返回这个数对 10^9 + 7 取模后得结果.
字符串 S 的子序列可以通过删去 S 中 0 个或多个字符得到. 一个序列如果是回文的, 那么它逆序后与原序列相等.
两个序列 A[1], A[2], … B[1], B[2], … 如果存在 A[i] != B[i], 那么这两个序列是不同的.

S 长度的范围为 [1, 1000].
S 中所有的字符 S[i] 均来自集合 {‘a’, ‘b’, ‘c’, ‘d’}.

Example
样例 1:

输入:“bccb”
输出:6
解释:
6 个不同的非空回文子序列为 “b”, “c”, “bb”, “cc”, “bcb”, “bccb”.
注意 bcb 只计一次, 即使它出现了两次
样例 2:

输入:“abcdabcdabcdabcdabcdabcdabcdabcddcbadcbadcbadcbadcbadcbadcbadcba”
输出:104860361
解释:
字符串 S 有3104860382个不同的非空回文子序列, 对 10^9 + 7 取模后得 104860361
Tags
Company
领英

https://www.cnblogs.com/beiyeqingteng/p/11206410.html

https://www.lintcode.com/problem/738/
*/

package main

/**
 * @param str: a string S
 * @return: the number of different non-empty palindromic subsequences in S
 */
func countPalindSubseq(str string) int {
	// write your code here
	var md int = 1e9 + 7
	if str == "" {
		return 0
	}
	var n int = len(str)
	if n <= 0 {
		return 0
	}
	var dp [][]int = make([][]int, n)
	for i := 0; i < n; i++ {
		dp[i] = make([]int, n)
		dp[i][i] = 1
	}
	for dis := 1; dis < n; dis++ {
		for i := 0; i < n - dis; i++ {
			var j int = i + dis
			if str[i] == str[j] {
				var low = i + 1
				var high = j - 1
				for {
					if low > high || str[low] == str[j] {
						break
					}
					low += 1
				}
				for {
					if low > high || str[high] == str[j] {
						break
					}
					high -= 1
				}
				if low > high {
					dp[i][j] = 2*dp[i+1][j-1] + 2
				} else if low == high {
					dp[i][j] = 2*dp[i+1][j-1] + 1
				} else {
					dp[i][j] = 2*dp[i+1][j-1] - dp[low+1][high-1]
				}
			} else {
				dp[i][j] = dp[i+1][j] + dp[i][j-1] - dp[i+1][j-1]
			}

			if dp[i][j] < 0 {
				dp[i][j] += md
			} else {
				dp[i][j] %= md
			}
		}
	}
	return dp[0][n-1]
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值