同样是一篇dp总结:
最长上升子序列
例题:https://vjudge.net/contest/278813#problem/C
普通写法的板子:(注意要从大往小找!!!)(待思索……)
#include <bits/stdc++.h>
#define ll long long
#define N 1005
//最长上升子序列,从大往小找的方法
using namespace std;
const int modd=1e9+7;
ll inf=0x3f3f3f3f;
ll dp[N];
ll an[N];
ll h,maxx=0;
int main()
{
int n;
while(cin>>n)
{
maxx=-1;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;++i)
{
cin>>an[i];
}
for(int i=n;i>=1;--i)
{
for(int j=1;j<i;++j)
{
if(an[i]>an[j]&&dp[i]+1>dp[j])
dp[j]=dp[i]+1;
}
}
for(int i=1;i<=n;++i)
maxx=max(maxx,dp[i]+1);
cout<<maxx<<endl;
}
return 0;
}
优化写法(利用二分函数lower_bound),板子如下:
#include <bits/stdc++.h>
#define ll long long
#define N 1005
//最长上升子序列,从大往小找的方法,快速二分法
using namespace std;
const int modd=1e9+7;
ll inf=0x3f3f3f3f;
ll dp[N];
ll an[N];
ll h,maxx=0;
int main()
{
int n;
while(cin>>n)
{
maxx=-1;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;++i)
{
cin>>an[i];
}
int len=1;
//拿dp[i]来当模拟栈
dp[1]=an[1];
for(int i=2;i<=n;++i)//注意是从
{
if(an[i]>dp[len])
{
dp[++len]=an[i];
}
else
{
int site=std::lower_bound(dp+1,dp+len+1,an[i])-dp;
dp[site]=an[i];
}
}
//lower_bound的右区间是开区间,如果找到了会返回地址,否则返回比这个值大一点的值的地址
cout<<len<<endl;
}
return 0;
}
最长公共子串
待更……