最長上升子序列
樸素算法 O(n*n)
dp[i]表示以a[i]爲末尾的最長上升子序列的長度
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn = 100010;
const int inf = 0x3f3f3f3f;
int a[maxn],dp[maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i = 0;i<n;i++)
{
scanf("%d",&a[i]);
dp[i] = 1;
}
int ans = 0;
for(int i = 1;i<n;i++)
{
for(int j = 0;j<i;j++)
if(a[j] < a[i])
dp[i] = max(dp[i],dp[j] + 1);
ans = max(ans,dp[i]);
}
printf("%d\n",ans);
}
}
O(nlogn)
dp[i] = 長度爲i+1的上升子序列中末尾元素的最小值,直接運用STL 中的lower_bound()很方便
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn = 100010;
const int inf = 0x3f3f3f3f;
int a[maxn],dp[maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i = 0;i<n;i++)
{
scanf("%d",&a[i]);
dp[i] = inf;
}
for(int i = 0;i<n;i++)
{
a[i] = *lower_bound(dp,dp+n,a[i]) = a[i];
}
printf("%d\n",lower_bound(dp,dp+n,inf) - dp);
}
}
最長公共子序列
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
string s1,s2;
int dp[1010][1010];
int main()
{
while(cin >> s1 >> s2)
{
int len1 = s1.length();
int len2 = s2.length();
memset(dp,0,sizeof dp);
for(int i = 1;i<=len1;i++)
{
for(int j = 1;j<=len2;j++)
{
if(s1[i-1] == s2[j-1])
{
dp[i][j] = dp[i-1][j-1] + 1;
}
else
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
}
cout<<dp[len1][len2]<<endl;
}
}