求最长公共子串有两种情况:1,要求子串连续。2,不要求子串连续
。
1.要求子串连续这种情况比较简单
原理如下:设定一个矩阵p,p[i][j]表示以str1[i]和str2[j]结尾的子串的最大公共子串的长度。利用如下递推式求解:
如果 str1[i] != str2[j], p[i][j] = 0.
如果 str1[i] = str2[j], p[i][j] = p[i-1][j-1] + 1.
2.要求子串不连续这种情况的递推式为:
如果 str1[i] != str2[j], p[i][j] = max(p[i-1][j], p[i][j-1]).
如果 str1[i] = str2[j], p[i][j] = p[i-1][j-1] + 1.
template<typename _Ty>
int common_cstr(const _Ty *A , const _Ty *B, int lenA=0, int lenB=0,int continuous = 1)
{
if(!A || !B)
return -1;
if(!lenA || !lenB)//既然你不指定长度,我只能认为你是字符串了...
{
lenA = strlen((char*)(A));
lenB = strlen((char*)(B));
}
int **poj = new int*[lenA];
for(int i = 0; i < lenA; i++)
{
poj[i] = new int[lenB];
memset(poj[i],0,lenB*sizeof(int)); //把矩阵元素全部置0
}
int max = 0;
int max_i ,max_j;
/*******************************公共部分-建立矩阵结束*********************************************/
/**********子串求解****************/
if(continuous == 1) //要求子串连续的情况
{
for(int i = 0; i < lenA; i++)
for(int j = 0; j < lenB; j++)
{
if(A[i] == B[j])
{
if(!i || !j)
poj[i][j] = 1;
else
poj[i][j] = poj[i-1][j-1] + 1;
}
if(poj[i][j] > max)//求解的过程中记录一下最长子串的长度,以及结尾的下标 用于后面打印结果使用
{
max = poj[i][j];
max_i = i;
max_j = j;
}
}
}
else //子串不连续
{
for(int i = 0; i < lenA; i++)
for(int j = 0; j < lenB; j++)
{
if(!i || !j)
{
if(A[i] == B[j])
poj[i][j] = 1;
else if(!i && j)
poj[i][j] = poj[i][j-1];
else if(i && !j)
poj[i][j] = poj[i-1][j];
}
else
{
if(A[i] == B[j])
poj[i][j] = poj[i-1][j-1] + 1;
else if(poj[i-1][j] > poj[i][j-1])
poj[i][j] = poj[i-1][j];
else
poj[i][j] = poj[i][j-1];
}
if(poj[i][j] > max)//求解的过程中记录一下最长子串的长度,以及结尾的下标 用于后面打印结果使用
{
max = poj[i][j];
max_i = i;
max_j = j;
}
}
}
/*****************找到子串起始位置*****************/
cout << "最长公共子串的长度为: " << max << endl;
cout << "公共子串的逆序为:" << endl;
if(continuous == 1)//连续的情况很简单
{
while(A[max_i] == B[max_j])
{
cout << A[max_i];
--max_i;
--max_j;
}
}
else
{
while(max_i >= 0 && max_j >= 0)
{
if(A[max_i] == B[max_j])
{
cout << A[max_i];
--max_i;
--max_j;
}
else
{
if(poj[max_i-1][max_j] > poj[max_i][max_j - 1] )
--max_i;
else
--max_j;
}
}
}
cout << endl;
for(int i = 0; i < lenA; i++)
delete []poj[i];
delete []poj;
return max;
}上述代码打印的子串很可能不是唯一的,要全部找出来可以遍历一下 poj矩阵找出所有最大值,然后根据相应的规则找出来
本文详细介绍了如何求解两个字符串之间的最长公共子串问题,包括连续子串和非连续子串两种情况,并提供了一段C++代码实现,通过构建矩阵来高效地解决问题。
1142

被折叠的 条评论
为什么被折叠?



