NYOJ 36 最長公共子序列
阿新 • • 發佈:2019-02-12
最長公共子序列
時間限制:3000ms | 記憶體限制:65535KB 難度:3- 描述
-
咱們就不拐彎抹角了,如題,需要你做的就是寫一個程式,得出最長公共子序列。
tip:最長公共子序列也稱作最長公共子串(不要求連續),英文縮寫為LCS(Longest Common Subsequence)。其定義是,一個序列 S ,如果分別是兩個或多個已知序列的子序列,且是所有符合此條件序列中最長的,則 S 稱為已知序列的最長公共子序列。- 輸入
-
第一行給出一個整數N(0<N<100)表示待測資料組數
接下來每組資料兩行,分別為待測的兩組字串。每個字串長度不大於1000. - 輸出
- 每組測試資料輸出一個整數,表示最長公共子序列長度。每組結果佔一行。
- 樣例輸入
-
2 asdf adfsd 123abc abc123abc
- 樣例輸出
-
3 6
/*求最長公共子序列。動態規劃問題。
設序列X = (x1; x2; . . . ; xm) 和Y =(y1; y2; . . . ; yn) 的最長公共子序列為
Z = (z1; z2; . . . ; zk),
則
. 若xm = yn,則zk = xm = yn,且Zk-1 是Xm-1 和Yn-1 的最長公共子序列。
. 若xm != yn 且zk != xm,則Z 是Xm-1 和Y 的最長公共子序列。
. 若xm != yn 且zk != yn,則Z 是X 和Yn-1 的最長公共子序列。
其中Xm-1 = (x1; x2; . . . ; xm-1), Yn-1 = (y1; y2; . . . ; yn-1), Zk-1 = (z1; z2; . . . ; zk-1)
*/
一般解法,不優化空間。
#include <stdio.h> #include <string.h> #define MAX 1010 int dp[MAX][MAX] = {0}; void lcs(const char *x, int m, const char *y, int n) { int i,j; for (i=0; i<=m; i++) { dp[i][0] = 0; } for (j=0;j<=n; j++) { dp[0][j] = 0; } for (i=1; i<=m; i++) { for (j=1; j<=n; j++) { if (x[i-1] == y[j-1]) { dp[i][j] = dp[i-1][j-1] + 1; } else { dp[i][j] = dp[i-1][j] > dp[i][j-1]?dp[i-1][j] : dp[i][j-1]; } } } } int main() { int m; char x[MAX],y[MAX]; scanf("%d",&m); while (m--) { int xlen,ylen; scanf("%s%s",x,y); xlen = strlen(x); ylen = strlen(y); lcs(x,xlen,y,ylen); printf("%d\n",dp[xlen][ylen]); } return 0; }
滾動陣列,優化空間
#include <stdio.h>
#include <string.h>
#define MAX 1001
short dp[2][MAX];
int main()
{
int m;
char x[MAX],y[MAX];
scanf("%d",&m);
while (m--)
{
int xlen,ylen;
int i,j,e = 0;
scanf("%s%s",x,y);
xlen = strlen(x);
ylen = strlen(y);
memset(dp,0,sizeof(dp));
for (i=1; i<=xlen;i++)
{
e = 1-e;
for (j=1; j<=ylen; j++)
{
if (x[i-1] == y[j-1])
{
dp[e][j] = dp[1-e][j-1] + 1;
}
else
{
dp[e][j] = dp[e][j-1] > dp[1-e][j]?dp[e][j-1] : dp[1-e][j];
}
}
}
printf("%d\n",dp[e][ylen]);
}
return 0;
}