A:最长公共子序列问题(LCS)之备忘录法
题目描述
使用备忘录法求解两个序列的最长公共子序列的长度。输入
每组输入包括两行,每行包括一个字符串。输出
两个序列的最长公共子序列的长度。
样例输入 Copy
ACBCDABD ABDCABA样例输出 Copy
5
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
string a,b;
int dp[N][N];
int lcs(int x,int y){
if(dp[x][y]!=-1){
return dp[x][y];
}
if(x==0||y==0){
dp[x][y]=0;
}
else if(a[x-1]==b[y-1]){
dp[x][y]=lcs(x-1,y-1)+1;
}
else{
dp[x][y]=max(lcs(x,y-1),lcs(x-1,y));
}
return dp[x][y];
}
void solve(){
cin>>a>>b;
memset(dp,-1,sizeof dp);
cout<<lcs(a.size(),b.size())<<"\n";
}
int main() {
cin.tie(0)->sync_with_stdio(false);
solve();
return 0;
}
B:最长公共子序列问题(LCS)之动态规划法
题目描述
使用动态规划算法求解两个序列的最长公共子序列的长度。
输入
每组输入包括两行,每行包括一个字符串。
输出
两个序列的最长公共子序列的长度。
样例输入 Copy
ACBCDABD ABDCABA样例输出 Copy
5
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
string a,b;
int dp[N][N];
void solve(){
cin>>a>>b;
for(int i=1;i<=a.size();i++){
for(int j=1;j<=b.size();j++){
if(a[i-1]==b[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[a.size()][b.size()]<<"\n";
}
int main() {
cin.tie(0)->sync_with_stdio(false);
solve();
return 0;
}
C:最长公共子序列问题(LCS)-构造LCS
题目描述
使用动态规划算法求两个序列的最长公共子序列,需构造一条最长公共子序列。
输入
每组输入包括两行,每行包括一个字符串。
输出
两个字符序列的一条最长公共子序列。(输入已确保最长公共子序列的唯一性)
样例输入 Copy
acdbxx ccdxx样例输出 Copy
cdxx
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
int dp[N][N];
void solve(){
string a,b;
while(cin>>a>>b){
memset(dp,0,sizeof dp);
for(int i=1;i<=a.size();i++){
for(int j=1;j<=b.size();j++){
if(a[i-1]==b[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
}
else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
string s="";
int i=a.size();
int j=b.size();
while(i>0&&j>0){
if(a[i-1]==b[j-1]){
s=a[i-1]+s;
i--;
j--;
}
else if(dp[i-1][j]>dp[i][j-1]){
i--;
}
else{
j--;
}
}
cout<<s<<"\n";
}
}
int main() {
cin.tie(0)->sync_with_stdio(false);
solve();
return 0;
}
D:牛牛的字符串
题目描述
牛牛有两个字符串(可能包含空格),他想找出其中最长的公共连续子串的长度,希望你能帮助他。例如:两个字符串分别为"abede"和"abgde",结果为2。
输入
每组数据包括两行,每行为一个字符串。
输出
输出最长的公共连续子串的长度。
样例输入 Copy
abede abgde样例输出 Copy
2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
string a,b;
void solve(){
while(cin>>a>>b){
int m=0;
for(int i=0;i<a.size();i++){
int n=0;
for(int j=0;j<b.size();j++){
if(a[i+n]==b[j]){
n++;
m=max(m,n);
}
else
n=0;
}
}
cout<<m<<"\n";
}
}
int main() {
cin.tie(0)->sync_with_stdio(false);
solve();
return 0;
}
E:最大子段和
题目描述
给定n个整数(可能是负数)组成的序列a[1], a[2], a[3], …, a[n],求该序列的子段和如a[i]+a[i+1]+…+a[j]的最大值。
输入
每组输入包括两行,第一行为序列长度n,第二行为序列。
输出
输出字段和的最大值。
样例输入 Copy
5 -1 0 1 2 3样例输出 Copy
6
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
void solve(){
int n;
while(cin>>n)
{
int s=0,m=0;
for(int i=1; i<=n; i++)
{
int a;
cin>>a;
s+=a;
m=max(m,s);
if(s<0)
s=0;
}
cout<<m<<"\n";
}
}
int main() {
cin.tie(0)->sync_with_stdio(false);
solve();
return 0;
}
F:最大子段和升级版
题目描述
使用动态规划算法求整数数组(可能包含负整数)的最大子段和,以及和最大子段的起始位置和结束位置:
例如:输入数组(6,-1,5,4,-7),输出14, 1, 4,其中14表示最大子段和,1表示和最大的子段从第1个数字开始,4表示和最大的子段到第4个数字结束,即(6, -1 , 5, 4)。输入
每组输入两行,第1行为数组中包含的整数个数n,第2行为n个整数(可能包含负整数),两两之间用空格隔开。
输出
输出最大子段和,以及和最大子段的起始位置和结束位置,两两之间用空格隔开。
样例输入 Copy
5 6 -1 5 4 -7样例输出 Copy
14 1 4
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
int a[N];
void solve(){
int n;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>a[i];
}
int sum=-1,ss=-1,s=0,l,r;
for(int i=0;i<n;i++){
if(ss<0){
ss=0;
s=i;
}
ss+=a[i];
if(sum<ss){
sum=ss;
l=s;
r=i;
}
}
cout<<sum<<" "<<l+1<<" "<<r+1<<"\n";
}
}
int main() {
cin.tie(0)->sync_with_stdio(false);
solve();
return 0;
}
G:最短的名字
题目描述
在一个奇怪的村子中,很多人的名字都很长,比如aaaaa, bbb and abababab。
名字这么长,叫全名显然起来很不方便。所以村民之间一般只叫名字的前缀。比如叫'aaaaa'的时候可以只叫'aaa',因为没有第二个人名字的前三个字母是'aaa'。不过你不能叫'a',因为有两个人的名字都以'a'开头。村里的人都很聪明,他们总是用最短的称呼叫人。输入保证村里不会有一个人的名字是另外一个人名字的前缀(作为推论,任意两个人的名字都不会相同)。
如果村里的某个人要叫所有人的名字(包括他自己),他一共会说多少个字母?
输入
输入第一行为数据组数T (T<=10)。每组数据第一行为一个整数n(1<=n<=1000),即村里的人数。以下n行每行为一个人的名字(仅有小写字母组成)。输入保证一个村里所有人名字的长度之和不超过1,000,000。
输出
对于每组数据,输出所有人名字的字母总数。
样例输入 Copy
1 3 aaaaa bbb abababab样例输出 Copy
5
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
void solve(){
int n;
cin>>n;
vector<string> a;
a.push_back(".");
for(int i=1;i<=n;i++){
string ss;
cin>>ss;
a.push_back(ss);
}
sort(a.begin()+1,a.end());
a.push_back(".");
int s=0;
for(int i=1;i<=n;i++){
string s1="",s2="",s3="";
for(int j=0;j<=a[i].size();j++){
s1+=a[i][j];
s2+=a[i+1][j];
s3+=a[i-1][j];
if(s1==s2||s1==s3){
continue;
}
else{
s+=j+1;
break;
}
}
}
cout<<s<<"\n";
}
int main() {
cin.tie(0)->sync_with_stdio(false);
int t;cin>>t;while(t--)
solve();
return 0;
}
H:最大计分
题目描述
小米和小花在玩一个删除数字的游戏。
游戏规则如下:
首先随机写下N个正整数,然后任选一个数字作为起始点,从起始点开始从左往右每次可以删除一个数字,但是必须满足下一个删除的数字要小于上一个删除的数字。每成功删除一个数字计1分。
请问对于给定的N个正整数,一局游戏过后可以得到的最大计分是多少?输入
单组输入。
第1行输入一个正整数N表示数字的个数(N<=10^3)。
第2行输入N个正整数,两两之间用空格隔开。输出
对于给定的N个正整数,一局游戏过后可以得到的最大计分值。
样例输入 Copy
6 3 4 3 5 2 1样例输出 Copy
4
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
int a[N],b[N];
void solve(){
int n,s=0;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
b[i]=1;
for(int j=1;j<i;j++)
if(a[j]>a[i])
b[i]=max(b[i],b[j]+1);
s=max(s,b[i]);
}
cout<<s<<"\n";
}
int main() {
cin.tie(0)->sync_with_stdio(false);
solve();
return 0;
}