D. Gargari and Permutations
题意:k个串,分别是1~n的某种排列,输出k个串的最长公共子序列。
思路:如果像两个串那样dp求LCS复杂度是O(n^k),是不行的。如果先求两个串的LCS,再和下一个串求LCS,直到最后一个串,也是不行的,因为两个串的LCS可能是多解的。我的方法是对每个串,如果串中i在j前面,就建一条边,然后对k个图进行与运算,合成一个图,再对这个图求最长路。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#define INF 1000000010
#define ll long long
#define max3(a,b,c) max(a,max(b,c))
#define MAXN 1000
using namespace std;
int num[6][1010];
int dp[1010];
bool m[6][1010][1010];
int n,K;
int dfs(int x){
if(dp[x]!=-1)return dp[x];
bool flag=false;
for(int i=1;i<=n;i++){
if(m[0][x][i]){
dp[x]=max(dp[x],dfs(i)+1);
flag=true;
}
}
if(!flag){
dp[x]=1;
return 1;
}
return dp[x];
}
int main(){
while(cin>>n>>K){
memset(dp,-1,sizeof(dp));
for(int i=1;i<=K;i++){
for(int j=1;j<=n;j++){
cin>>num[i][j];
}
}
for(int k=1;k<=K;k++){
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
m[k][num[k][i]][num[k][j]]=1;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
m[0][i][j]=1;
for(int k=1;k<=K;k++){
m[0][i][j]&=m[k][i][j];
}
}
}
int ans=0;
for(int i=1;i<=n;i++){
ans=max(ans,dfs(i));
}
cout<<ans<<endl;
}
return 0;
}

该博客探讨了Codeforces Round #264 (Div. 2) D题目的解决方案,主要关注如何找到k个字符串的最长公共子序列。博主指出,传统的动态规划方法(如O(n^k))不适用于此问题,因为存在多解可能。提出的策略是构建基于字符串中字符相对顺序的图,并通过图的与运算来合并k个图,最终在合成图上寻找最长路径以得到答案。
1349

被折叠的 条评论
为什么被折叠?



