P1439 【模板】最长公共子序列

34 篇文章 0 订阅
7 篇文章 0 订阅

https://www.luogu.com.cn/problem/P1439

题目描述

给出1-n的两个排列P1和P2,求它们的最长公共子序列。

输入格式

第一行是一个数n,

接下来两行,每行为n个数,为自然数1-n的一个排列。

输出格式

一个数,即最长公共子序列的长度

输入输出样例

输入 #1复制

5 
3 2 1 4 5
1 2 3 4 5

输出 #1复制

3

说明/提示

【数据规模】

对于50%的数据,n≤1000

对于100%的数据,n≤100000

 

【题目分析】这个题首先我们需要想到的是经典的最长公共子序列问题,那么复杂度为N^2,可以得到50分,这里我就直接展示代码了。

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int a[N],b[N],f[N][N];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int j=1;j<=n;j++) cin>>b[j];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		{
			f[i][j]=f[i-1][j];
			if(a[i]==b[j])
			{
				f[i][j]=max(f[i][j],1);
				for(int k=1;k<j;k++)
					f[i][j]=max(f[i][j],f[i-1][k]+1);
			}
		}
	int res=0;
	for(int i=1;i<=n;i++) res=max(res,f[n][i]);
	cout<<res<<endl;
	return 0;
}

对于第二个思路是这样的,我们因为这是一个1到n的排列,这个其实是对这两个数组做一个共同的映射,然后求出来一个最长上升子序列就可以了。

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int a[N],q[N],b[N],m[N];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i],m[a[i]]=i;
    for(int i=1;i<=n;i++) cin>>b[i],a[i]=m[b[i]];
    q[1]=-2e9;
    int len=1;
    for(int i=1;i<=n;i++)
    {
        int l=1,r=len;
        while(l<r)
        {
            int mid=l+r+1>>1;
            if(q[mid]<a[i]) l=mid;
            else r=mid-1;
        }
        len=max(len,r+1);
        q[r+1]=a[i];
    }
    cout<<len-1<<endl;
    return 0;
}

 

### 回答1: 以下是最长公共子序列的C语言实现: ```c #include <stdio.h> #include <string.h> #define MAX_LENGTH 100 int max(int a, int b) { return a > b ? a : b; } int lcs(char *str1, char *str2) { int len1 = strlen(str1); int len2 = strlen(str2); int dp[MAX_LENGTH][MAX_LENGTH]; int i, j; for (i = 0; i <= len1; i++) { dp[i][0] = 0; } for (j = 0; j <= len2; j++) { dp[0][j] = 0; } for (i = 1; i <= len1; i++) { for (j = 1; j <= len2; j++) { if (str1[i - 1] == str2[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } } } return dp[len1][len2]; } int main() { char str1[MAX_LENGTH], str2[MAX_LENGTH]; printf("请输入字符串1:"); scanf("%s", str1); printf("请输入字符串2:"); scanf("%s", str2); printf("最长公共子序列的长度为:%d\n", lcs(str1, str2)); return 0; } ``` 这个程序实现了两个字符串的最长公共子序列的长度。 ### 回答2: 最长公共子序列(Longest Common Subsequence)是一种常用的字符串匹配算法,在文本处理、数据压缩等领域有广泛的应用。下面是一个使用C语言实现最长公共子序列算法的模板: ```c #include <stdio.h> #include <string.h> #define MAX_LENGTH 100 int lcs(char* str1, char* str2, int m, int n) { int lcsTable[MAX_LENGTH][MAX_LENGTH], i, j; for (i = 0; i <= m; i++) { for (j = 0; j <= n; j++) { if (i == 0 || j == 0) lcsTable[i][j] = 0; else if (str1[i - 1] == str2[j - 1]) lcsTable[i][j] = lcsTable[i - 1][j - 1] + 1; else lcsTable[i][j] = (lcsTable[i - 1][j] > lcsTable[i][j - 1]) ? lcsTable[i - 1][j] : lcsTable[i][j - 1]; } } return lcsTable[m][n]; } int main() { char str1[MAX_LENGTH], str2[MAX_LENGTH]; int result; printf("请输入第一个字符串:"); scanf("%s", str1); printf("请输入第二个字符串:"); scanf("%s", str2); result = lcs(str1, str2, strlen(str1), strlen(str2)); printf("最长公共子序列的长度为:%d\n", result); return 0; } ``` 在该模板中,我们首先定义一个二维数组lcsTable来存储最长公共子序列的长度。然后,我们使用两个for循环遍历两个字符串的所有字符,对每个字符进行匹配。如果两个字符相等,则当前位置的lcsTable[i][j]值就等于上一个位置的值加1;如果不相等,则当前位置的值等于上方或左方的较大值。最后,返回lcsTable[m][n]即为最长公共子序列的长度。 在main函数中,我们先输入两个字符串,然后调用lcs函数计算最长公共子序列的长度,最后输出结果。 请注意,该模板仅实现了最长公共子序列的长度计算,如果需要获取最长公共子序列本身,请根据情况进行修改。 ### 回答3: 最长公共子序列问题是一个经典的动态规划问题,可以通过使用动态规划算法来解决。下面是一个使用C语言编写的最长公共子序列模板程序。 ```c #include <stdio.h> #include <string.h> int max(int a, int b) { return (a > b) ? a : b; } int lcs(char* X, char* Y, int m, int n) { int L[m + 1][n + 1]; int i, j; for (i = 0; i <= m; i++) { for (j = 0; j <= n; j++) { if (i == 0 || j == 0) L[i][j] = 0; else if (X[i - 1] == Y[j - 1]) L[i][j] = L[i - 1][j - 1] + 1; else L[i][j] = max(L[i - 1][j], L[i][j - 1]); } } return L[m][n]; } int main() { char X[] = "ABC"; char Y[] = "ABCD"; int m = strlen(X); int n = strlen(Y); printf("最长公共子序列的长度为:%d\n", lcs(X, Y, m, n)); return 0; } ``` 该模板程序中的 `lcs` 函数接受两个字符串 `X` 和 `Y`,以及两个字符串的长度 `m` 和 `n` 作为参数。函数中定义了一个二维数组 `L[m + 1][n + 1]`,用于保存中间结果。接下来,使用两个嵌套循环来填充数组 `L`,直到达到最终的结果。最终,返回 `L[m][n]` 即为最长公共子序列的长度。 在 `main` 函数中,定义了两个字符串 `X` 和 `Y`,并使用 `strlen` 函数来获取它们的长度。然后,调用 `lcs` 函数来计算最长公共子序列的长度,并将结果打印输出。 这个模板程序可以根据具体问题进行修改和扩展,来解决更加复杂的最长公共子序列问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值