1. 程式人生 > >POJ-1458 最長公共子序列

POJ-1458 最長公共子序列

這個題的意思就是說:

給一個序列 A 和 B ,讓你求他們的共同的子序列的長度,這些子序列可以不在原來的字串中連續排列。

這個題的話,我們可以使用動態規劃的思路,我們假設 MaxLen [ i ] [ j ] 是 A 串和 B 串中從一開始的,A 串中的的第 i 個字元和B 串中的第 j 個字元的最長公共子序列的長度。

我們可以知道 MaxLen[i][0]是0,並且 MaxLen[0][j]也是0,這是邊界條件。

然後對於以後的如果 a串的第 i個字元和 b串的第 j個字元相等的話,我們就可以讓 MaxLen [i][j]加一,如果不相等的話我們就從

maxlen[i][j-1] 和maxlen[j][i-1]中選一個大的出來作為它的值。

對於一個不做證明,第二個也很好證明,主要是因為,既然 MaxLen [i][j] 不大於MaxLen [i][j-1]和 MaxLen [i-1][j],並且 MaxLen [i][j]

不小於 MaxLen [i][j-1] 和 MaxLen [i-1][j] ,所以,他們可以說是相等的關係。

怎麼證明這個,對於不小於不再作證明了,不大於的話我們用反證就可以了。

因為如果它大於 減一 這個類的話,說明,第 i 個字元起作用了,因為 i-1 並沒有這個字元,說明它就是最後一個字元,同理 j-1也是最後一個字元,既然他們都是最後一個字元,並且都起了作用, 說明他們相等,而我們的前提是 i-1 不等於 j-1,所以推出矛盾,假設不成立。

#include <iostream>
#include <cstring>
using namespace std;
char sz1[1000];
char sz2[1000];
int MaxLen[1000][1000]; 
using namespace std;
int main()
{
	while (cin>>sz1>>sz2) {
		int len1=strlen(sz1);
		int len2=strlen(sz2);
		for (int i=0;i<=len1;i++) {
			MaxLen[i][0]=0;
		}
		for (int j=0;j<=len2;j++) {
			MaxLen[0][j]=0;
		}
		for (int i=1;i<=len1;i++) {
			for (int j=1;j<=len2;j++) {
				if (sz1[i-1]==sz2[j-1]) {
					MaxLen[i][j]=MaxLen[i-1][j-1]+1;
				}
				else {
					MaxLen[i][j]=max(MaxLen[i-1][j],MaxLen[i][j-1]);
				}
			}
		}
		cout<<MaxLen[len1][len2]<<endl;
	}
	return 0;
}