最长公共子序列,典型的动态规划问题,需要认真分析
maxLen[i][j] 代表s1 s2分别位于数学上的i j 位时 具有最长连续公共子序列的长度
这样可以说,在i为0或者j为0时 maxLen[i][j] = 0 即没有最长公共子序列
精髓的代码在这一部分
if(s1[i-1]==s2[j-1])//如果这两个位置的元素相等
{
maxlen[i][j] = maxlen[i-1][j-1] + 1;
}
else
{
maxlen[i][j] = max(maxlen[i-1][j],maxlen[i][j-1]);
}
如果当前位置相同,则这个位置的最长上升长度等于之前一位的上升长度加一
如果当前位置不同 则这个位置的最长上升长度等于i相同j不同 或者i不同j相同位置两者的最大值 这两者一个抛弃了当前i一个抛弃了当前j
(菜鸡弱弱吐槽一下OJ...这几天POJ频发大姨妈不知道怎么回事。。。WF都金牌了还不好好修修OJ 还曾经出现了一大波卡waiting的情况,题目链接先给百练上的了)
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
char s1[1005];
char s2[1005];
int maxlen[1005][1005]; //这个是最关键的 前一半代表s1位置到i的时候 (这里是生活中的位置)
//后一半代表s2位置到i的时候 最长公共子序列的长度
int main(void)
{
while(cin>>s1>>s2)
{
int len1 = strlen(s1);
int len2 = strlen(s2);
for(int i=0;i<len1;i++)
{
maxlen[i][0] = 0;//这里代表到第0位 (数学中的第0位 最长公共子序列的值是1 即有可能没有公共子序列)
}
for(int i=0;i<len2;i++)
{
maxlen[0][i] = 0;
}
//这个题主要要注意 由于一开始要求角标>=0 所以要用数学上的角标考虑maxlen部分
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;j++)
{
if(s1[i-1]==s2[j-1])//如果这两个位置的元素相等
{
maxlen[i][j] = maxlen[i-1][j-1] + 1;
}
else
{
maxlen[i][j] = max(maxlen[i-1][j],maxlen[i][j-1]);
}
}
}
printf("%d\n",maxlen[len1][len2]);
}
}