hdoj 5495 LCS 【统计元素个数大于1的置换群数目】【LCS变形】

本文介绍了一种解决最长公共子序列(LCS)问题的有效算法,该算法针对两个由1到n组成的序列,寻找特定排列使得LCS长度最大化。通过对置换群进行分析,仅付出一个元素的代价即可获得接近最优的LCS长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



LCS

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 23    Accepted Submission(s): 12


Problem Description
You are given two sequence {a1,a2,...,an} and {b1,b2,...,bn}. Both sequences are permutation of {1,2,...,n}. You are going to find another permutation{p1,p2,...,pn} such that the length of LCS (longest common subsequence) of {ap1,ap2,...,apn} and {bp1,bp2,...,bpn} is maximum.
 

Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains an integer n(1n105) - the length of the permutation. The second line contains n integers a1,a2,...,an. The third line contains nintegers b1,b2,...,bn.

The sum of n in the test cases will not exceed 2×106.
 

Output
For each test case, output the maximum length of LCS.
 

Sample Input
2 3 1 2 3 3 2 1 6 1 5 3 2 6 4 3 6 2 4 5 1
 

Sample Output
2 4
 



题意:给两个由1~n组成的n个数序列a[]和b[],让你找到一个1~n的序列p[],使得a[p[1]] , a[p[2]] ... a[p[n]]  和 b[p[1]], b[p[2]]... b[p[3]]的LCS最大,输出最大的LCS。


分析:对于一个有n个元素的置换群,我们可以付出一个元素的代价得到n-1长度的LCS。

思路:统计元素个数大于1的置换群个数ans,答案就是 n - ans。为了方便可以用pos[i]记录a或b序列中元素i所在的位置。


AC代码:


#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 100000+10
using namespace std;
struct rec
{
    int a, b;
};
rec num[MAXN];
bool vis[MAXN];
int pos[MAXN];
int main()
{
    int t, n;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &num[i].a);
            pos[num[i].a] = i;
        }
        //int cnt = 0;
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &num[i].b);
//            if(num[i].a == num[i].b)
//                cnt++;
        }
        memset(vis, false, sizeof(vis));
        int ans = 0;
        for(int i = 0; i < n; i++)
        {
            if(vis[num[i].a]) continue;
            int j = num[i].b;
            int have = 1;
            while(j != num[i].a)
            {
                vis[j] = true;
                int next = pos[j];
                have++;
                j = num[next].b;
            }
            ans += have > 1 ? 1 : 0;
            //ans = max(have, ans);
        }
        printf("%d\n", n-ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值