整理一下动态规划与子串子序列相关的内容:
花了一天时间,重新做了一遍,感觉手很生,有些地方调试了很久才好,唉。
- 最长公共子序列:
- 带路径输出的最长公共子序列:
- 最长公共子串:
- 最长上升子序列:
- 最长上升子串:
- 最长回文子序列:
- 最长回文子串:
1.最长公共子序列:
#define MAX 1000
int arr[MAX + 1][MAX + 1] { 0 };
int main()
{
string s1;
string s2;
int i, j;
cin >> s1 >> s2;
for (i = 1; i <= s1.size(); i++)
{
for (j = 1; j <= s2.size(); j++)
{
if (s1[i - 1] == s2[j - 1])
{
arr[i][j] = arr[i - 1][j - 1] + 1;
}
else
{
arr[i][j] = max(arr[i - 1][j], arr[i][j - 1]);
}
}
}
cout << "最长公共子序列长度为:" << arr[s1.size()][s2.size()] << endl;
return 0;
}
2.带路径输出的最长公共子序列:
#define MAX 1000
int arr[MAX + 1][MAX + 1] { 0 };
int road[MAX + 1][MAX + 1] { 0 };
int main()
{
string s1;
string s2;
int i, j;
cin >> s1 >> s2;
for (i = 1; i <= s1.size(); i++)
{
for (j = 1; j <= s2.size(); j++)
{
if (s1[i - 1] == s2[j - 1])
{
arr[i][j] = arr[i - 1][j - 1] + 1;
road[i][j] = 1;
}
else
{
if (arr[i][j - 1] >= arr[i-1][j])
{
arr[i][j] = arr[i][j - 1];
road[i][j] = 2;
}
else
{
arr[i][j] = arr[i - 1][j];
road[i][j] = 3;
}
}
}
}
i = s1.size();
j = s2.size();
string lcs;
while (i >= 1 && j >= 1)
{
if (road[i][j] == 1)
{
lcs += s1[i - 1];
i--;
j--;
}
else if (road[i][j] == 2)
{
j--;
}
else
{
i--;
}
}
int half = lcs.size() / 2;
for (i = 0; i < half; i++)
{
char temp = lcs[i];
lcs[i]=lcs[lcs.size() - 1 - i];
lcs[lcs.size() - 1 - i] = temp;
}
cout << "最长公共子序列长度为:" << arr[s1.size()][s2.size()] << endl;
cout << "最长公共子序列为:" << lcs << endl;
//----------------end
for (i = 0; i <= s1.size(); i++)
{
for (j = 0; j <= s2.size(); j++)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
cout<<endl;
for (i = 0; i <= s1.size(); i++)
{
for (j = 0; j <= s2.size(); j++)
{
cout << road[i][j] << " ";
}
cout << endl;
}
return 0;
}
3.最长公共子串:
#define MAX 1000
int arr[MAX + 1][MAX + 1] { 0 };
int main()
{
string s1;
string s2;
int i, j;
int maxlen;
int pos;
maxlen = 0;
cin >> s1 >> s2;
for (i = 1; i <= s1.size(); i++)
{
for (j = 1; j <= s2.size(); j++)
{
if (s1[i - 1] == s2[j - 1])
{
arr[i][j] = arr[i - 1][j - 1] + 1;
if (arr[i][j] > maxlen)
{
maxlen = arr[i][j];
pos = i - 1;
}
}
else
{
arr[i][j] = 0;
}
}
}
cout << "最长公共子串长度为:" << maxlen << endl;
cout << "最长子串为:";
for (i = pos-(maxlen-1); i <= pos; i++)
{
cout << s1[i];
}
cout << endl;
for (i = 0; i <= s1.size(); i++)
{
for (j = 0; j <= s2.size(); j++)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
return 0;
}
4.最长上升子序列:
#define MAX 1000
int dp[MAX + 1]{ 0 };
vector<int> s;
int main()
{
int n;
int k;
int i, j;
int maxlen = 0;
cin >> n;
for (i = 0; i < n; i++)
{
cin >> k;
s.push_back(k);
}
if (s.size() <= 1) cout << s.size() << endl;
for (i = 0; i < n; i++)
{
dp[i] = 1;
for (j = 0; j < i; j++)
{
if (s[j] < s[i])
{
dp[i] = max(dp[i], dp[j] + 1);
}
}
if (dp[i] > maxlen)
{
maxlen = dp[i];
}
}
cout << "最长上升子序列长度为:" << maxlen << endl;
cout << endl;
for (i = 0; i < s.size(); i++)
{
cout << dp[i] << " ";
}
return 0;
}
5.最长上升子串:
这个与动态规划没关系,但强迫症忍不了啊,就加上去吧
int main()
{
string s;
cin >> s;
if (s.size() <= 1)
{
cout << s << endl;
}
int maxlen = 1;
int len = 1;
int i;
for (i = 1; i < s.size(); i++)
{
if (s[i - 1] < s[i])
{
len++;
if (maxlen < len)
{
maxlen = len;
}
}
else
{
len = 1;
}
}
cout << maxlen << endl;
return 0;
}
6.最长回文子序列:
最长回文子序列和回文子串这边就有些难度了,特别是(7.)回文子串那边,搞了好几个小时才跑出正确结果,而且leetcode上跑的结果还和本地不一样也挺神奇的。
#define MAX 1000
int arr[MAX + 1][MAX + 1] { 0 };
//abacdfgdcaba
int main()
{
string s;
cin >> s;
int i, j;
int maxlen = 0;
int pos = 0;
for (i = s.size() - 1; i >= 0; i--)
{
arr[i][i] = 1;
for (j = i+1; j < s.size(); j++)
{
if (s[i] == s[j])
{
arr[i][j] = j - i == 1 ? 2 : ( arr[i + 1][j - 1] + 2 );
}
else
{
arr[i][j] = max(arr[i + 1][j], arr[i][j - 1]);
}
}
}
cout << "最长回文子序列长度为:" << arr[0][s.size()-1] << endl;
cout << endl;
for (i = 0; i < s.size(); i++)
{
for (j = 0; j < s.size(); j++)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
return 0;
}
7.最长回文子串:
#define MAX 1000
int arr[MAX + 1][MAX + 1] { 0 };
//abacdfgdcaba
int main()
{
string s;
cin >> s;
int i, j;
int maxlen = 0;
int pos=0;
for (i = s.size() - 1; i >= 0; i--) //因为arr[i][j]的递推用到了arr[i+1][j-1], 所以需要反过来计算
{
for (j = i; j < s.size(); j++)
{
if (s[i] == s[j] && ( j - i <= 1 || arr[i + 1][j - 1] == 1 ))//~!!!!!!!!!!!或语句顺序不能反,因为当i=0,j=1的时候后面arr[i+1][j-1]会超出数组范围
{
arr[i][j] = 1;
if (j - i + 1 > maxlen)
{
maxlen = j - i + 1;
pos = i;
}
}
}
}
cout << "最长回文子串长度为:" << maxlen << endl;
cout << "回文串为:";
for (i = pos; i < pos + maxlen; i++)
{
cout << s[i] << " ";
}
cout << endl;
for (i = 0; i < s.size(); i++)
{
for (j = 0; j < s.size(); j++)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
return 0;
}