#include #include #include using std::string; using std::cout; using std::endl; // for 'a' ~ 'd' static const int X_MAX = 'd' - 'a'; static const int N_MAX = 1000; static int dp[3][N_MAX][N_MAX][X_MAX + 1]; class Solution { private: static const int MOD = 1000000007; public: int countPalindromicSubsequences(string S) { int n = S.size(), ans = 0, memset_size = sizeof(dp[0]); memset(dp, 0, sizeof(dp)); for (int len = 1; len <= n; len++) { for (int sep = len - 1; sep < n; sep ++) { for (int i = 0; i + sep < n; i++) { int j = i + sep; int a = S[i] - 'a', b = S[j] - 'a'; for (int x = 0; x <= X_MAX; x++) if (x != a && x != b && 1 < sep) dp[0][i][j][x] = dp[0][i + 1][j - 1][x]; if (a == b) { if (len <= 2) dp[0][i][j][a] = 1; else for (int x = 0; x <= X_MAX; x++) dp[0][i][j][a] = (dp[0][i][j][a] + dp[2][i + 1][j - 1][x]) % MOD; } else if (0 < sep) { dp[0][i][j][a] = dp[0][i][j - 1][a]; dp[0][i][j][b] = dp[0][i + 1][j][b]; } } } for (int x = 0; x <= X_MAX; x++) ans = (ans + dp[0][0][n - 1][x]) % MOD; // Use scrolling array to save memory memcpy(dp[2], dp[1], memset_size); memcpy(dp[1], dp[0], memset_size); memset(dp[0], 0, memset_size); } return ans; } }; // Input: // S = 'abcdabcdabcdabcdabcdabcdabcdabcddcbadcbadcbadcbadcbadcbadcbadcba' // Output: 104860361 // bccb // len 0: // len 1: b c // len 2: bb cc // len 3: bcb // len 4: bccb // dp[1][0][0]['b'] = 1, dp[1][1][1]['c'] = 1, dp[1][2][2]['c'] = 1, dp[1][3][3]['b'] = 1 // dp[len][i][j][x] means different palindroms count which start / end with 'x' between s[i] and s[j], length is len // loop len, sep, i // j = i + sep // for x != s[i] and x != s[j]: // dp[len][i][j][x] = dp[len][i + 1][j - 1][x] // s[i] == s[j] == a: // dp[len][i][j][a] = sum(dp[len - 2][i + 1][j - 1][every x]) // s[i] == a, s[j] == b, a != b: // dp[len][i][j][a] = dp[len][i][j - 1][a], // dp[len][i][j][b] = dp[len][i + 1][j][b] int main() { Solution* sol = new Solution; string input; input = "addd"; cout << "actual: " << sol->countPalindromicSubsequences(input) << ", expected: " << 4 << endl; input = "bccb"; cout << "actual: " << sol->countPalindromicSubsequences(input) << ", expected: " << 6 << endl; input = "abcdabcdabcdabcdabcdabcdabcdabcddcbadcbadcbadcbadcbadcbadcbadcba"; cout << "actual: " << sol->countPalindromicSubsequences(input) << ", expected: " << 104860361 << endl; input = "baaddaaabaddccbbbdcbcccbdbdabdabdbadabddbbcbbcabbccdaccdbcbbcdcdbaadbcadacabcaaaadbcaddbbacddcdabaadcacacdcabaadacadcccdcbbcdabdcdacaacdcdbdacbdbcdcbaddaccabaaaabcadacdaddbcccbcdbadbdddaaabbdbdbcbcdab"; cout << "actual: " << sol->countPalindromicSubsequences(input) << ", expected: " << 431300010 << endl; input = "bdccbdbdcaacaadbdacaadabbdaababacbdbadaccccbbbccbdbddcacdbbcdaaababddadbbcabaddbbaabcdacdcddcbacdcadddbaadcbbccdcbdcaaabcbddacaccadacdcadacadccabdbadcdabaaccbcabbacdcbbbabddbcccbcbcddacaccabbabccdbbabacadbbdbcccbddaaadcdaddcccddaacbddabddabadbcbaadcaddbdccabaddcccdccbacaccccbcdccacbabddcbcbbbdbbddaabbcaddbddddaacbbccbcdbadacccbadbccdddadcbacbbdcabcbdbbaabcdcbdacabacdccdaabcbbddbdddcacdbdccbbabbaccdcbabcdacdabdddaddacdbddabcbbbdcccacbdadddbbdbcabccadbcbadddcbcddaababcabbbcbbabadaddabcbdacaadcababcbacadcdabcdbddadaadddddbaaacddaacadcdbaaacbacaabdabccbacabbabddacddcdacdcddbacbddbdcadcddabdadcdbcbbcadbcdabbbbdcdadadbbcadbcbbcccccabdaabcdacbdbcadabcdbaaaaacdaaabcdcaabddcacdcacabbaadbdbcbaaabadbdadadaccddacababbdcbaaaccaabbdaddadcabaabbdaadadcabcabbdbbdccbabbbabbcbcbdcacccbdbabdbaadccdaddaddaadadccabdcbbbccacbbaaabccaccdcabbbddbdbbacdaabbdcdacbdddbacbadccabbbdbbbdbdbcadcacddddcdbdcabccdccabaadbcbacaaababdddcbcdaaabaaabddbcabcbbcdddccdcbccbbccadccaaccccbdadcaacdcbcabacacadaabacddaadcccbcabdad"; cout << "actual: " << sol->countPalindromicSubsequences(input) << ", expected: " << 739921586 << endl; return 0; }