D. Gargari and Permutations
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
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.
Sample test(s)
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].
#include<list>
#include<vector>
#include<stack>
#include<iostream>
#include<stdio.h>
using namespace std;
int arr[7][1003];
int Val[7][1003];
list<int> lst[1004];
int visited[1002];
int dist[1004];
int ans=INT_MIN;
void dfs(int st)
{
visited[st]=1;
list<int>::iterator it;
for(it=lst[st].begin();it!=lst[st].end();it++)
{
if(!visited[*it])
dfs(*it);
dist[st]=max(dist[st],dist[*it]+1);
}
dist[st]=max(dist[st],1);
ans=max(ans,dist[st]);
}
int main()
{
int N;
int K;
int a;
int f=0;
cin>>N>>K;
for(int i = 1; i <= K; ++ i)
for(int j = 1; j <= N; ++ j)
{
scanf("%i", &Val[i][j]);
arr[i][ Val[i][j] ] = j;
}
for(int i = 1; i <= N; ++ i)
for(int j = 1; j <= N; ++ j)
{
if(i == j) continue;
bool flag = 1;
for(int k = 1; k <= K; ++ k)
if(arr[k][i] >= arr[k][j])
flag = 0;
if(flag==1) lst[i].push_back(j);
}
for(int i=1;i<=N+1;i++)
{
dist[i]=INT_MIN;
}
for(int i=1;i<=N;i++)
{
if(visited[i]==0)
{
dfs(i);
}
}
cout<<ans<<endl;
return 0;
}
**code ends here**
The question can be generalised as finding the LCS of k strings. It is implemented using directed acyclic graph. The procedure of composed of 2 steps
(1) Forming the graph
We can build a directed acyclic graph with n nodes.If j is after i in all vectors then we add in graph edge (i,j).
The graph using adjacency list representation would look like
1 - 2 , 3
2- 3
3- none
4-3
Now we have formed a directed acyclic graph . Now the 2nd part is finding longest path in the graph
(2) Finding longest path in the graph
Now we recursively call dfs from all unvisited nodes. As soon as we reach the leaf we update its value by max(dist[leafnode],1) and then update the answer accordingly.
as the call to a dfs ends we update the value of the parent as max of the (1*dist[child], dist[st]).
The answer is max of all values.
Remembering this question is very important as these helps in finding LCS of many strings. This can be also done using DP the solution of which is highly recommended. Here is the Dynamic Programming solution
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; int pos[6][1003]; int a[6][1003]; int dp[1003]; int N, K; int main(){ scanf("%d%d", &N, &K); for(int i=1;i<=K;++i){ for(int j=1;j<=N;++j){ scanf("%d", &a[i][j]); pos[i][a[i][j]] = j; } } int ans = 1; dp[N] = 1; for(int i=N-1;i>=1;--i){ dp[i] = 1; for(int j=i+1;j<=N;++j){ bool ok = true; for(int k=1;k<=K;++k){ if(pos[k][a[1][i]] > pos[k][a[1][j]]){ ok = false; break; } } if(ok){ dp[i] = max(dp[i], 1+dp[j]); } } ans = max(ans, dp[i]); } printf("%d\n",ans); return 0; }