题目
题目描述 给定两个字符串str1和str2,输出两个字符串的最长公共子串 题目保证str1和str2的最长公共子串存在且唯一。 示例1
输入"1AB2345CD",“12345EF” 返回值 “2345”
思路
动态规划的典型例子,要想好状态怎么变化。
在这里用二维数组保存状态,假设 字符串为 123 ,12 。
则有一开始状态:
* | 1 | 2 | 3 |
---|---|---|---|
1 | |||
2 |
然后
1 | 2 | 3 | |
---|---|---|---|
1 | 0+1=1 | 0 | 0 |
2 | 0 | 1+1=2 | 0 |
所以对于一个格子状态判断是这样的:
- 若两个字符相同,状态为左上角格子状态+1
- 若两个字符不同,状态归0 (因为子串要求连续)
代码
class Solution {
public:
/**
* longest common substring
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @return string字符串
*/
string LCS(string str1, string str2) {
// write code here
int len1 = str1.size();
int len2 = str2.size();
//if(len1<len2) swap(str1,str2);
int **map;
map = new int* [len2+1];
for(int i=0;i<=len2;i++){
map[i] = new int[len1+1];
}
for(int i=0;i<=len2;i++){
for(int j=0;j<=len1;j++){
map[i][j] = 0;
}
}
int maxj=0,maxlen=0;
for(int i=1;i<=len2;i++){
for(int j=1;j<=len1;j++){
if(str2[i-1] == str1[j-1]){
map[i][j] = map[i-1][j-1]+1;//相等记录为左上角+1
if(maxlen < map[i][j]){//需要更新max
maxj = j;
maxlen = map[i][j];
}
// cout<<i<<endl;
}
else{
map[i][j] = 0 ;//不相等归0
}
}
}
auto res = str1.substr(maxj-maxlen,maxlen);
return res;
}
};
类比一下差不多的题目,最长公共子序列。
子序列不要求相同的字母连续出现。
所以一个格子的状态变换为:
- 若两个字符相同,取左上角状态+1或左边状态中最大那个为自己状态
- 若不同,则取左边格子状态为自己状态