(写之前写一些废话:这是本人的第二篇博客,很感谢能帮到大家,祝大家学业有成!)
子串与子序列的区别(很重要的!!!)
子串 必须连续
子序列 可以连续,可以不连续
搞清楚之后,进入正题
问题一 最长公共子序列
题目 https://www.luogu.com.cn/problem/P1439
数组的定义:
f[i][j]:a[1...i]与b[1...i]的最长公共子序列的长度(以i结尾)
转移(有点难懂):
if(a[i]==b[i]) f[i][j]=f[i-1][j-1]+1(如果相等,这个最长公共子序列的长度+1)
else f[i][j]=max(f[i-1][j],f[i][j-1])(不相等,由于是子序列(可以不连续),后面的数字可能还是该子序列的,继承长度(形象点说就是:虽然我不是,但我后面的数可能是,所以我要把这个名额给他们留着))
边界(还算简单?):
f[0][0]=0(我们是从1开始的,0不用管啦) f[0][j]=f[i][0]=0(同理)
答案:
f[n][n](在例题中两个数组长度均为n,如果长度不一样用f[n][m])
完整代码:
#include<bits/stdc++.h>
using namespace std;
int dp[1001][1001],a1[2001],a2[2001],n,m;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)scanf("%d",&a1[i]);
for(int i=1;i<=n;i++)scanf("%d",&a2[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(a1[i]==a2[j]) dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
cout<<dp[n][n];
}
当然,例题时间有点大,的代码绝对过不了(
那你讲半天在干什么),在后面的文章中,我会讲解简化的代码~
问题二 最长公共子串
题目 https://www.luogu.com.cn/problem/SP1811
数组的定义(好像有点眼熟?):
f[i][j]:a[1...i]与b[1...i]的最长公共字串的长度(以i结尾)
转移(简单多了):
if(a[i]==b[i]) f[i][j]=f[i-1][j-1]+1(如果相等,这个最长公共子串的长度+1)
else f[i][j]=0(不相等,直接为0(不愧是子串,比子序列粗暴多了))
边界(一模一样):
f[0][0]=0(我们是从1开始的,0不用管啦) f[0][j]=f[i][0]=0(同理)
答案:
在f[1...n][1...m]中找到最大值
完整代码(例题是字符串(没找到整数),整数的话改下数据类型就行了):
#include<bits/stdc++.h>
using namespace std;
string a,b;
int f[25001][25001],ans=0;
int main(){
cin>>a>>b;
for(int i=0;i<=a.size();i++){
for(int j=0;j<=b.size();j++)
f[i][j]=0;
}
for(int i=1;i<=a.size();i++){
for(int j=1;j<=b.size();j++){
if(a[i]==b[j]){
f[i][j]=f[i-1][j-1]+1;
ans=max(ans,f[i][j]);
}
else f[i][j]=0;
}
}
cout<<ans;
}
问题三 最长上升序列
题目 https://www.luogu.com.cn/problem/B3637
数组的定义(终于是一维了):
f[i]:a[1...i]最长上升子序列的长度(以i结尾)
转移:
If(a[j]<a[i]) f[i]=max(f[j]+1,f[i])(因为可以不连续,所以讨论的是“要不要a[i]”(此处与问题四不同))
边界:
a[1...n]=1
答案:
在f[1...n]中找到最大值
完整代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int f[10001],a[10001],ans=0;
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
f[i]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=i-1;j++){
if(a[j]<a[i]){
f[i]=max(f[j]+1,f[i]);
ans=max(ans,f[i]);
}
}
}
cout<<ans;
}
问题四 最长上升子串
题目 https://www.luogu.com.cn/problem/U454718
这个堪称几个中最简单的了
呃...我懒了,相信凭借着你极致的脑子,绝对看得懂
代码:
#include<bits/stdc++.h>
using namespace std;
int n,a[10001],f[10001],ans=1;
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
f[1]=1;
for(int i=1;i<=n;i++){
if(a[i-1]<a[i]){
f[i]=f[i-1]+1;
ans=max(ans,f[i]);
}
else f[i]=1;
}
cout<<ans;
}
啊!!!为了写这篇文章自己出了一道题,洛谷的题量还是不够
写了2小时,感谢你看完~下期见~~~