D. Gargari and Permutations[求最长公共字序列]

D. Gargari and Permutations

Gargari got bored to play with the bishops and now, after solving the problem about them, he is trying to do math homework. In a math book he have found k permutations. Each of them consists of numbers 1, 2, ..., n in some order. Now he should find the length of the longest common subsequence of these permutations. Can you help Gargari?

You can read about longest common subsequence there: https://en.wikipedia.org/wiki/Longest_common_subsequence_problem

Input

The first line contains two integers n and k (1 ≤ n ≤ 1000; 2 ≤ k ≤ 5). Each of the next k lines contains integers 1, 2, ..., n in some order — description of the current permutation.

Output

Print the length of the longest common subsequence.

Examples

input

4 3
1 4 2 3
4 1 2 3
1 2 4 3

output

3

Note

The answer for the first test sample is subsequence [1, 2, 3].

 

在做这道题之前,你需要分清楚两个概念,一个是最长公共子串,一个是最长公共子序列。串和序列的不同之处在哪呢?

子序列可以理解为在给定的序列中将一些数字拿掉后得到的结果,而串的要求是这个结果在原序列中是连续的。

举一个简单的例子:

1 3 2 4 5
1 2 3 4 5

在这个例子中最长公共字串是:4 5

而最长公共子序列则可以为:1 3 4 5   or  1 2 4 5

这就是两者的区别。两个求法都可以使用dp,用空间换取时间,具体怎么求,请自行百度。

 

题意:求k个长度为n且为n的全排列的序列的最长公共子序列

题解:这个子序列肯定会和第一个序列有关,所以我们只需要枚举第一个序列就行了,对于后面的几个序列,我们用一个数组保存每个数字的位置。假设第一个数列用a[n]数组保存,当a[i]这个数在a[j]钱面时,如果后面的几个序列的a[i]的位置也同时在a[j]前面,那么就可以得出d[j] = max(d[i]+1,d[j]);

#include<bits/stdc++.h>
using namespace std;
int a[6][2005];
int b[6][2005];
int dp[2005];
int n,k;
int check(int x,int y)
{
	for(int i=2;i<=k;i++)
	{
		if(b[i][x]>b[i][y]) return 0; 
	}
	return 1;
}
int main()
{
	
	cin>>n>>k;
	for(int i=1;i<=k;i++)
	  for(int j=1;j<=n;j++){
	  	 cin>>a[i][j];
	  	 b[i][a[i][j]]=j;
	  }
	for(int i=1;i<=n;i++) dp[i]=1;
    
    for(int i=1;i<=n;i++)
      for(int j=i+1;j<=n;j++)
      {
      	  if(check(a[1][i],a[1][j]))
      	  dp[j] = max(dp[i]+1,dp[j]);
	  }
	  int ans=0;
	  for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
	  cout<<ans<<endl;
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值