#include <iostream>
#include <vector>
#include <string>
using namespace std;
string longestPalindrome(string s)
{
int n = s.size();
vector<vector<bool>>dp(n,vector<bool>(n));
int start = 0, end = 0;
for(int i = n - 1; i >= 0; --i)
{
for(int j = i; j < n; ++j)
{
if(s[i] == s[j] && (j - i < 2 || dp[i+1][j-1]))
{
if(end - start < (j - i))
{
start = i;
end = j;
}
dp[i][j] = true;
}
}
}
return s.substr(start,end-start+1);
}
int dfs(string s,int i,int j, vector<vector<int>>&memo)
{
if(i > j) return 0;
if(i == j) return 1;
if(memo[i][j] != -1)return memo[i][j];
if(s[i] == s[j])memo[i][j] = dfs(s,i+1,j-1,memo) + 2;
else memo[i][j] = max(dfs(s,i+1,j,memo),dfs(s,i,j-1,memo));
return memo[i][j];
}
int longestPalindromeSubseq(string s)
{
int n = s.size();
vector<vector<int>>memo(n,vector<int>(n,-1));
return dfs(s,0,n-1,memo);
}
int longestPalindromeSubseqII(string s)
{
int n = s.size();
vector<vector<int>>dp(n,vector<int>(n));
for(int i = n - 1; i >= 0; --i)
{
dp[i][i] = 1;
for(int j = i + 1; j < n; ++j)
{
if(s[i] == s[j])dp[i][j] = dp[i + 1][j-1] + 2;
else dp[i][j] = max(dp[i][j-1],dp[i+1][j]);
}
}
return dp[0][n-1];
}
int lcs(string r, string s)
{
int m = r.size();
int n = s.size();
vector<vector<int>>dp(m+1,vector<int>(n+1,0));
for(int i = 0; i < m; ++i)
{
for(int j = 0; j < n; ++j)
{
if(r[i] == s[j])
{
dp[i+1][j+1] = dp[i][j] + 1;
}
else
{
dp[i+1][j+1] = max(dp[i+1][j],dp[i][j+1]);
}
}
}
return dp[n][n];
}
bool isValidPalindrome(string s, int k)
{
string r = s;
reverse(s.begin(),s.end());
return (r.size() - lcs(r,s)) <= k;
}
int main()
{
//LeetCode5
string s = "babad";
cout << longestPalindrome(s) << endl;
//LeetCode516
s = "bbbab";
cout << longestPalindromeSubseq(s) << endl;
cout << longestPalindromeSubseqII(s) << endl;
//LeetCode1216
s = "abcdeca";
int k = 2;
cout << isValidPalindrome(s,k) << endl;
return 0;
}