您的位置:首页 > 其它

LCS-基础

2015-08-10 13:14 387 查看
最长公共子序列和最长公共连续子串:

          最长公共连续子串(Longest CommonSubstring) 和最长公共子序列(LongestCommon Subsequence, LCS)的区别:子串(Substring)是串的一个连续的部分,子序列(Subsequence)则是从不改变序列的顺序,而从序列中去掉任意的元素而获得的新序列;更简略地说,前者(子串)的字符的位置必须连续,后者(子序列LCS)则不必。

比如:字符串  acdfg   和   akdfc  

            最长公共连续子串:          df

            最长公共子序列是:      adf。

最长公共子序列       

代码1:

#include<cstdio>
#include<cstring>
#define max(x,y) (x>y?x:y)

char ch1[1010],ch2[1010];
int dp[1010][1010];

int main()
{
while(scanf("%s%s",ch1,ch2)!=EOF)
{
memset(dp,0,sizeof(dp));
int len1=strlen(ch1);
int len2=strlen(ch2);
int i,j;

for(i=1;i<=len1;++i) //模板
{
for(j=1;j<=len2;++j)
{
if(ch1[i-1]==ch2[j-1])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}

printf("%d\n",dp[len1][len2]);
}
return 0;
}代码2:
#include<cstdio>
#include<cstring>
#define max(x,y) (x>y?x:y)

int len1,len2;
int dp[1010][1010];
int bj[1010][1010];
char ch1[1010],ch2[1010];

void LCS()   //lcs最长公共子序列模板
{
int i,j;
for(i=1;i<=len1;++i)
{
for(j=1;j<=len2;++j)
{
if(ch1[i-1]==ch2[j-1])
{
dp[i][j]=dp[i-1][j-1]+1;
bj[i][j]=1;
}
else if(dp[i-1][j]>=dp[i][j-1])
{
dp[i][j]=dp[i-1][j];
bj[i][j]=0;
}
else
{
dp[i][j]=dp[i][j-1];
bj[i][j]=2;
}
}
}
}

void PRINTF(int i,int j)  //输出最长公共子序列
{
if(i==0||j==0)
return ;
if(bj[i][j]==1)
{
PRINTF(i-1,j-1);
printf("%c",ch1[i-1]);
}
else if(bj[i][i]==0)
PRINTF(i-1,j);
else
PRINTF(i,j-1);
}

int main()
{
int len;
while(scanf("%s%s",ch1,ch2)!=EOF)
{
memset(dp,0,sizeof(dp));  //清零
memset(bj,0,sizeof(bj));

len1=strlen(ch1);
len2=strlen(ch2);

LCS();

len=dp[len1][len2];  //最长公共子序列的长度
printf("%d\n",len);

PRINTF(len1,len2);  //输出最长公共子序列
printf("\n");
}
return 0;
}

最长公共连续子串    代码:

//找出两个字符串的最长公共连续子串的长度

#include<cstdio>
#include<cstring>

char ch1[1010],ch2[1010];
char ch[1010];  //存放最大连续子串
int bj[1010][1010];
int len1,len2,max_len,xi,yj;

void LCS_string()  //最大连续子串长度
{
int i,j;
max_len = -1;
for(i=1;i<len1+1;i++)
{
for(j=1;j<len2+1;j++)
{
if(ch1[i-1]==ch2[j-1])
bj[i][j]=bj[i-1][j-1]+1;
else
bj[i][j]=0;

if(bj[i][j]>max_len)
{
max_len=bj[i][j];
xi=i;
yj=j;
}
}
}
}

void MAX_string()  //求最大连续子串
{
int n=max_len;
int i,j;
ch[n--]='\0';
i=xi-1;
j=yj-1;
while(i>=0&&j>=0)
{
if(ch1[i]==ch2[j])
{
ch[n--]=ch1[i];
i--;
j--;
}
else
break;
}
}

int main()
{
while(scanf("%s%s",ch1,ch2)!=EOF)
{
len1=strlen(ch1);
len2=strlen(ch2);
memset(ch,'\0',sizeof(ch));
memset(bj,0,sizeof(bj));

LCS_string();

printf("最大连续子串长度:     %d\n",max_len);

MAX_string();

printf("最大连续子串:         %s\n",ch);
}
return 0;
}


最长公共连续子串(动态)     代码:

//找出两个字符串的最长公共连续子串的长度

#include<cstdio>
#include<cstring>

int len1,len2,max_len,xi,yj;
char ch1[1000],ch2[1000];
char ch[1010];

void LCS_string()
{
int i,j;

int **bj = new int*[len1+1];  //动态申请的二维数组

for(i = 0; i < len1+1; i++)
bj[i] = new int[len2+1];

for(i = 0; i < len1+1; i++)
bj[i][0]=0;        //第0列都初始化为0
for(j = 0; j < len2+1; j++)
bj[0][j]=0;        //第0行都初始化为0

max_len = -1;
for(i = 1 ; i < len1+1 ; i++)
{
for(j = 1; j < len2+1; j++)
{
if(ch1[i-1]==ch2[j-1])     //只需要跟左上方的c[i-1][j-1]比较就可以了
bj[i][j]=bj[i-1][j-1]+1;
else                         //不连续的时候还要跟左边的c[i][j-1]、上边的c[i-1][j]值比较,这里不需要
bj[i][j]=0;

if(bj[i][j]>max_len)
{
max_len=bj[i][j];
xi=i;
yj=j;
}
}
}

for(i = 0; i < len1+1; i++)         //释放动态申请的二维数组
delete[] bj[i];
delete[] bj;
}

void MAX_string()  //求最大连续子串
{
int n=max_len;
int i=xi-1,j=yj-1;
ch[n--]='\0';
while(i>=0 && j>=0)
{
if(ch1[i]==ch2[j])
{
ch[n--]=ch1[i];
i--;
j--;
}
else       //只要有一个不相等,就说明相等的公共字符断了,不连续了
break;
}

}

int main()
{
while(scanf("%s%s",ch1,ch2)!=EOF)
{
len1=strlen(ch1);
len2=strlen(ch2);
memset(ch,'\0',sizeof(ch));
LCS_string();

printf("最长公共子串长度:    %d\n",max_len);

MAX_string();
printf("最长公共子串为:     ");
printf("%s\n",ch);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息