编程:给定两个字符串A,B(只包含26个英文字母),输出所有公共的最长子字符串(如果出现重复子串,则输出多次)
输入包括两行,每行为一个连续字符串(大小写敏感)
输出包括多行,每行为扫描到的最长公共子串,按照该子串在字符串A(即第一行输入字符串)中出现的先后次序输出
abcxyzabcrst
opqrstabc
样例输出:
abc
abc
rst
动态规划
假设两个字符串分别为s和t,s[i]
和t[j]
分别表示其第i
和第j
个字符(字符顺序从0
开始),再令L[i, j]
表示以s[i]
和s[j]
为结尾的相同子串的最大长度。应该不难递推出L[i, j]
和L[i+1,j+1]
之间的关系,因为两者其实只差s[i+1]
和t[j+1]
这一对字符。若s[i+1]
和t[j+1]
不同,那么L[i+1, j+1]
自然应该是0
,因为任何以它们为结尾的子串都不可能完全相同;而如果s[i+1]
和t[j+1]
相同,那么就只要在以s[i]
和t[j]
结尾的最长相同子串之后分别添上这两个字符即可,这样就可以让长度增加一位。合并上述两种情况,也就得到L[i+1,j+1]=(s[i]==t[j]?L[i,j]+1:0)
这样的关系。
#include<iostream>
#include<vector>
using namespace std;
int main()
{
string str1 = "abcxyzabcrst";
string str2 = "opqrstabc";
int max = 0;
vector<vector<int>> c(str1.size() + 1, vector<int>(str2.size() + 1,0));
for (int i = 0; i < str1.size() + 1;i++)
for (int j = 0; j < str2.size() + 1; j++)
{
if (i == 0 || j == 0) c[i][j] = 0;
else if (str1[i - 1] == str2[j - 1])
{
c[i][j] = c[i - 1][j - 1]+1;
max=max>c[i][j] ? max : c[i][j];
}
else
{
c[i][j] = 0;
}
}
for (int i = 0; i < str1.size() + 1; i++)
for (int j = 0; j < str2.size() + 1; j++)
{
if (c[i][j] == max)
{
for (int k = max; k>0; --k)
{
cout << str1[i- k];
}
cout << endl;
}
}
return 0;
}