#include <iostream>
#include <string>
#include <vector>
using namespace std;
int lcs(string text1,string text2)
{
int n1 = text1.size(), n2 = text2.size();
vector<vector<int>>dp(n1 + 1,vector<int>(n2+1));
for(int i = 1; i <= n1; ++i)
{
for(int j = 1; j <= n2; ++j)
{
if(text1[i-1] == text2[j-1])
{
dp[i][j] = 1 + dp[i-1][j-1];
}
else
{
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[n1][n2];
}
int help(string t1,string t2,int p1,int p2, vector<vector<int>>& memo)
{
if(p1 >= t1.size() || p2 >= t2.size())return 0;
if(memo[p1][p2]!=0)return memo[p1][p2];
if(t1[p1] == t2[p2])return 1 + help(t1,t2,p1+1,p2+1,memo);
else return max(help(t1,t2,p1 + 1,p2,memo),help(t1,t2,p1,p2+1,memo));
}
int lcsI(string t1,string t2)
{
int n1 = t1.size(), n2 = t2.size();
vector<vector<int>>memo(n1,vector<int>(n2));
return help(t1,t2,0,0,memo);
}
bool isInterleave(string s1,string s2,string s3)
{
int m = s1.size(), n = s2.size();
if((m + n) != s3.size())return false;
vector<vector<bool>>dp(m+1,vector<bool>(n + 1));
dp[0][0] = true;
for(int i = 1; i <= m; ++i)
{
dp[i][0] = s3[i-1] == s1[i-1] && dp[i-1][0];
}
for(int i = 1; i <= n; ++i)
{
dp[0][i] = s3[i-1] == s2[i-1] && dp[0][i-1];
}
for(int i = 1; i <= m; ++i)
{
for(int j = 1; j <= n; ++j)
{
dp[i][j] = (s3[i + j - 1] == s1[i-1] && dp[i-1][j]) || (s3[i+j-1]==s2[j-1] &&dp[i][j-1]);
}
}
return dp[m][n];
}
int editDis(string w1,string w2)
{
int m = w1.size(), n = w2.size();
vector<vector<int>>dp(m + 1, vector<int>(n + 1));
for(int i = 0; i <= m; ++i)
{
dp[i][0] = i;
}
for(int j = 0; j <= n; ++j)
{
dp[0][j] = j;
}
for(int i = 1; i <= m; ++i)
{
for(int j = 1; j <= n; ++j)
{
if(w1[i-1] == w2[j-1])
{
dp[i][j] = dp[i-1][j-1];
}
else
{
dp[i][j] = min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1])) + 1;
}
}
}
return dp[m][n];
}
int numDistinct(string r,string t)
{
int m = r.size(), n = t.size();
vector<vector<int>>dp(m+1,vector<int>(n + 1));
for(int i = 0; i <= m; ++i)dp[i][0] = 1;
for(int i = 1; i <= m; ++i)
{
for(int j = 1; j <= n; ++j)
{
if(r[i-1] == t[j-1])
{
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
}
else
{
dp[i][j] = dp[i-1][j];
}
}
}
return dp[m][n];
}
bool isMatch(string s, string p)
{
int m = s.size(), n = p.size();
vector<vector<bool>>dp(m+1,vector<bool>(n+1));
for(int i = 0; i <= m; ++i)
{
for(int j = 0; j <= n; ++j)
{
if(i == 0 && j == 0)
{
dp[i][j] = true;
continue;
}
if(j == 0)
{
dp[i][j] = false;
continue;
}
if(p[j-1]!='*')
{
if(i > 0 && (p[j-1] =='.' || s[i-1] == p[j-1]))
{
dp[i][j] = dp[i-1][j-1];
}
}
else
{
if(j-2 >= 0)dp[i][j] = dp[i][j] | dp[i][j-2];
if(i >= 1 && j >= 2)dp[i][j] =dp[i][j] |
(( dp[i-1][j] && (p[j-2] == '.') || p[j-2] == s[i-1]));
}
}
}
return dp[m][n];
}
bool isMatchI(string s, string p)
{
int m = s.size(), n = p.size();
vector<vector<bool>>dp(m + 1, vector<bool>(n + 1));
dp[0][0] = true;
for(int j = 1; j <= n; ++j)
{
if(p[j - 1] == '*')
{
dp[0][j] = dp[0][j-1];
}
}
for(int i = 1; i <= m; ++i)
{
for(int j = 1; j <= n; ++j)
{
if(p[j-1] == s[i-1] || p[j-1] == '?')
dp[i][j] = dp[i-1][j-1];
else if (p[j-1] == '*')
dp[i][j] = dp[i-1][j] || dp[i][j-1];
}
}
return dp[m][n];
}
int minInsertions(string s)
{
string r = s;
reverse(r.begin(),r.end());
return s.size() - lcs(r,s);
}
int longestPalindromeSubseq(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 + 1][j],dp[i][j-1]);
}
}
return dp[0][n-1];
}
bool isValidPalindrome(string s, int k)
{
string r = s;
reverse(r.begin(),r.end());
return s.size() - lcs(r,s) <= k;
}
int main()
{
//LeetCode1143
string text1 = "abcde",text2 = "ace";
cout << lcs(text1,text2) << endl;
cout << lcsI(text1,text2) << endl;
//LeetCode97
string s1 = "aabcc";
string s2 = "dbbca";
string s3 = "aadbbcbcac";
cout << isInterleave(s1,s2,s3) << endl;
//LeetCode72
string word1 = "horse", word2 = "ros";
cout << editDis(word1,word2) << endl;
//LeetCode115
string s = "rabbbit",t = "rabbit";
cout << numDistinct(s,t) << endl;
//LeetCode10
s = "aa";
string p = "a*";
cout << isMatch(s,p) << endl;
//LeetCode44
s = "aa",p = "*";
cout << isMatchI(s,p) << endl;
//LeetCode1312
s = "mbadm";
cout << minInsertions(s) << endl;
//LeetCode516
s = "bbbab";
cout << longestPalindromeSubseq(s) << endl;
//LeetCode1216
s = "abcdeca";
int k = 2;
cout << isValidPalindrome(s,k) << endl;
return 0;
}