730. 统计不同回文子序列
统计不同回文子序列
题目描述:
给定一个字符串 s,返回 s 中不同的非空「回文子序列」个数 。
通过从 s 中删除 0 个或多个字符来获得子序列。
如果一个字符序列与它反转后的字符序列一致,那么它是「回文字符序列」。
如果有某个 i , 满足 ai != bi ,则两个序列 a1, a2, … 和 b1, b2, … 不同。
注意:
结果可能很大,你需要对 109 + 7 取模 。
示例 1:
输入:s = ‘bccb’
输出:6
解释:6 个不同的非空回文子字符序列分别为:’b’, ‘c’, ‘bb’, ‘cc’, ‘bcb’, ‘bccb’。
注意:’bcb’ 虽然出现两次但仅计数一次。
示例 2:
输入:s = ‘abcdabcdabcdabcdabcdabcdabcdabcddcbadcbadcbadcbadcbadcbadcbadcba’
输出:104860361
解释:共有 3104860382 个不同的非空回文子序列,104860361 对 109 + 7 取模后的值。
提示:
1 <= s.length <= 1000
s[i] 仅包含 ‘a’, ‘b’, ‘c’ 或 ‘d’
思路:
时间复杂度:O(),空间复杂度O()
三维dp
代码:
func countPalindromicSubsequences(s string) (ans int) {
const mod int = 1e9 + 7
n := len(s)
dp := [4][][]int{}
for i := range dp {
dp[i] = make([][]int, n)
for j := range dp[i] {
dp[i][j] = make([]int, n)
}
}
for i, c := range s {
dp[c-'a'][i][i] = 1
}
for size :=2; size<=n;size++{
for i,j := 0,size-1;j<n;i++{
for k,c := 0,byte('a');k<4;k++{
if s[i]==c && s[j] != c{
dp[k][i][j] = dp[k][i][j-1]
}
if s[i]!=c && s[j] == c{
dp[k][i][j] = dp[k][i+1][j]
}
if s[i]!=c && s[j] != c{
dp[k][i][j] = dp[k][i+1][j-1]
}
if s[i] == c && s[j] == c{
dp[k][i][j] = (2 + dp[0][i+1][j-1] + dp[1][i+1][j-1] + dp[2][i+1][j-1] + dp[3][i+1][j-1]) % mod
}
c++
}
j++
}
}
for _, d := range dp {
ans += d[0][n-1]
}
return ans % mod
}
代码效率:
执行用时:92 ms, 在所有 Go 提交中击败了45.75%的用户
内存消耗:64.6 MB, 在所有 Go 提交中击败了39.13%的用户
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!