最长上升子序列:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n,ans=1;
int sequence[10000],f[10000];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&sequence[i]);
/*f[1] = 1;
for(int i=2;i<=n;++i)
{
f[i]=1;//到i为止的最长上升子序列长度
for(int j=1;j<i;++j)
if(sequence[j]<sequence[i])//“<=”不下降子序列
f[i]=max(f[i],f[j]+1);
}
printf("%d",f[n]);*/
f[1]=sequence[1];
for(int i=2;i<=n;i++)
{
if(sequence[i]>f[ans])
f[++ans]=sequence[i];
else
{
/*int l=1,r=ans;
while(l<r)
{
int mid=(l+r+1)/2;
if (f[mid]<=sequence[i])
l=mid;
else
r=mid-1;
}
int j=l;*/
int j=upper_bound(f+1,f+ans+1,sequence[i])-f;
f[j]=sequence[i];
}
}
printf("%d",ans);
return 0;
}
最长公共子序列:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int f[5000][5000];
char a[10000],b[10000];
int main()
{
while(~scanf("%s%s",a+1,b+1))
{
int len1=strlen(a+1);
int len2=strlen(b+1);
f[0][0]=0;//a串匹配到第i位,b串第j位的最长公共子序列长度
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;j++)
{
f[i][j]=max(f[i-1][j],f[i][j-1]);
if(a[i]==b[j])//注意不要写成a[i]==b[i]
f[i][j]=max(f[i][j],f[i-1][j-1]+1);
}
}
printf("%d\n",f[len1][len2]);
}
return 0;
}
最长公共子串:
Codevs 1425 最长公共子串
取前两个字符串求最长公共子串。
再用公共子串和下一个字符串找公共子串,以此类推。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int mod = 100000000;
char a[1000010],b[1000010];
int n,ans,lan,lbn,pos;
int dp[3010][3010];
int main()
{
scanf("%d",&n);
scanf("%s",a+1);
lan=strlen(a+1);
for(int i=2;i<=n;i++)
{
ans=0;
scanf("%s",b+1);
lbn=strlen(b+1);
for(int i=1;i<=lan;i++)
{
for(int j=1;j<=lbn;j++)
{
if(a[i]==b[j])
{
dp[i][j]=dp[i-1][j-1]+1;
if(dp[i][j]>ans)
{
ans=dp[i][j];
pos=j;
}
}
}
}
memset(a,0,sizeof(a));
int tmp=ans;
for(int i=1;i<=ans;i++)
a[i]=b[pos-tmp+1],tmp--;
lan=strlen(a+1);
}
for(int i=1;i<=ans;i++)
printf("%c",a[i]);
return 0;
}
最长公共上升子序列:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,maxn,ans;
int a[100000],b[100000],f[5000][5000];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
//scanf("%d",&m);
m=n;
for(int i=1;i<=m;i++)
scanf("%d",&b[i]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i]!=b[j])
f[i][j]=f[i-1][j];
if(a[i]==b[j])
{
maxn=0;
for(int k=1;k<=j-1;k++)
{
if(b[j]>b[k])
maxn=max(maxn,f[i-1][k]);
}
f[i][j]=maxn+1;
}
}
}
for(int i=1;i<=m;i++)
ans=max(ans,f[n][i]);
printf("%d",ans);
return 0;
}
最大子段和:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,ans;
int num[1000010],dp[1000010];//dp[i]以i结尾的最大子段和
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
for(int i=1;i<=n;i++)
{
if(dp[i-1]>0)
dp[i]=dp[i-1]+num[i];//这样若dp[i]为正数,正确,若为负数,一定不会作为答案不影响正确性
else dp[i]=num[i];//前面的负数必然不能使当前值更大
if(dp[i]>ans)
ans=dp[i];
}
printf("%d",ans);
return 0;
}