最长公共子串和最长公共子序列
最长公共子串:在两个字符串中找到一个最长的公共子串,要求子串在原串中是连续的。
最长公共子序列:在两个字符串中找到一个最长的公共子串,不要求子串在原串中是连续的。
用矩阵描述起来,显而易见,由于本人描述能力较差,现推荐一篇博文。
http://www.cnblogs.com/zhangchaoyang/articles/2012070.html
以下是本人根据该文章中的讲解所实现的代码:
#include <stdio.h> #include <string.h> #define MAX_STR_LEN 1000 /* 最长公共字串(连续) 21232523311324 312123223445 */ int lcs(char *str1, char *str2) { int i, j; int nMaxLen = 0; int nPosOfMaxS = 0; int nLen1 = strlen(str1); int nLen2 = strlen(str2); int nTmpArray1[MAX_STR_LEN]; int nTmpArray2[MAX_STR_LEN]; for(i=0; i<MAX_STR_LEN; ++i) { nTmpArray1[i] = 0; nTmpArray2[i] = 0; } for(i=0; i<nLen1; ++i) { for(j=0; j<nLen2; ++j) { if(str1[i] == str2[j]) { if(j>0) { nTmpArray2[j] = nTmpArray1[j-1] + 1; } else { nTmpArray2[j] = 1; } if(nTmpArray2[j] > nMaxLen) { nMaxLen = nTmpArray2[j]; nPosOfMaxS = j; } } else { nTmpArray2[j] = 0; } } memcpy(nTmpArray1, nTmpArray2, MAX_STR_LEN); } str2[nPosOfMaxS+1] = 0; printf("%d %d\n", nPosOfMaxS, nMaxLen); printf("%s\n", str2 + nPosOfMaxS-nMaxLen +1); return 0; } /* 最长公共子序列(非连续) GCCCTAGCG GCGCAATG */ int PrintRes(char *str1, int *res, int pos, int maxlen) { if(maxlen == 1) { printf("%c", str1[pos]); return 0; } //printf("[%d][%d]\n", __LINE__, pos); PrintRes(str1, res, res[pos], maxlen-1); printf("%c", str1[pos]); return 0; } int LCS(char *str1, char *str2) { int i, j; int nMaxLen = 0; int nPosOfMaxS = 0; int nTmpMax = 0; int nLen1 = strlen(str1); int nLen2 = strlen(str2); int nTmpArray1[MAX_STR_LEN]; int nTmpArray2[MAX_STR_LEN]; int nResArray[MAX_STR_LEN]; for(i=0; i<MAX_STR_LEN; ++i) { nTmpArray1[i] = 0; nTmpArray2[i] = 0; nResArray[i] = 0; } for(i=0; i<nLen1; ++i) { nResArray[i] = nPosOfMaxS; for(j=0; j<nLen2; ++j) { nTmpArray2[j] = 0; //左上 if(str1[i]==str2[j] && j>0) { nTmpArray2[j] = nTmpArray1[j-1] + 1; } else if(j > 0) { nTmpArray2[j] = nTmpArray1[j-1]; } else if(str1[i] == str2[j]) { nTmpArray2[j] = 1; } //左 if(j>0 && nTmpArray2[j-1]>nTmpArray2[j]) { nTmpArray2[j] = nTmpArray2[j-1]; } //上 if(i>0 && nTmpArray1[j]>nTmpArray2[j]) { nTmpArray2[j] = nTmpArray1[j]; } //printf("%d %d %d %d %d\n", __LINE__, i, j, nTmpArray2[j], nResArray[i]); if(nTmpArray2[j]>nMaxLen) { nMaxLen = nTmpArray2[j]; nPosOfMaxS = i; //printf("%d %d %d\n", __LINE__, nMaxLen, i); } } memcpy(nTmpArray1, nTmpArray2, MAX_STR_LEN); } PrintRes(str1, nResArray, nPosOfMaxS, nMaxLen); printf("\n"); return 0; } int main() { char str1[MAX_STR_LEN]; char str2[MAX_STR_LEN]; scanf("%s", str1); scanf("%s", str2); lcs(str1, str2); LCS(str1, str2); return 0; }
在最长公共子序列中,我的结果和该文章的讲解不同,但长度是一样的。由于我们以不同的终点开始递归输出,导致了不同的结果。
posted on 2012-08-29 16:36 favourmeng 阅读(1639) 评论(0) 编辑 收藏 举报