Hi All :-)
I think some of you may read this problem from hackerrank. Here is the link:
https://www.hackerrank.com/challenges/dynamic-programming-classics-the-longest-common-subsequence
Since the test data is so weak, the traditional O(mn) solution can pass all the test data. So let's assume the two strings can be as long as 10^5. In this case, how to solve this problem? I guess the time complexity of the solution should be O(500*10^5) but have no idea to code it ... :-(
Deleted
I think Hirschberg algorithm can be implemented in O(n*n*log(n)) time and O(n) space. But I don't know is it enough to get AC because i don't know time limit
Function int solveLCS(String x, String y) should return whole vector K[1]. And instead of
there should be
wikipedia say's there is O(n*m) implementation of Hirschberg algorithm.
UPD: I was wrong. My algorithm also takes O(n*m) time, without Log(n) multiplier.
There is an algorithm faster than O(N*M). Suppose that the sequences are A and B. For each element that occurs in A write its positions in B in decreasing order.
For the given case:
5 6
1 2 3 4 1
3 4 1 2 1 3
It should look like this:
1 -> (5,3)
2 -> (4)
3 -> (6,1)
4 -> (2)
Then replace each element in A with its list:
(5,3) (4) (6,1) (2) (5,3)
5 3 4 6 1 2 5 3
Find one of its longest increasing subsequences X(There are a lot of algorithms for doing this fast like binary search, fenwick tree, segment tree and so on).
Then just print B[X1], B[X2], ..., B[Xk].
For example we can take 3, 4 and 6 as an increasing subsequence. Then we just print B[3]=1, B[4]=2 and B[6]=1 which is a valid answer.
Edit: It's not faster every time. If there is a case where all numbers in the sequences are the same it will be slower. But it's good with random test cases. When you make the list for each number you can check which of the algorithms is better to use.
You're wrong. Your algorithm fails on a very simple test:
Furthermore, it is believed (or even proved, I'm not sure) that general LCS problem cannot be solved in o(NM).
Why do you think that it fails? The list for 1 is (2,1) and the sequence is 2 1 2 1. Its longest increasing subsequence is of length 2 -> 1 2. And the answer is B[1], B[2] -> 1 1. It's not wrong.
Note: We are to find a LCS of two sequences :)
Yep, sure, it should be LCS :)
Yes, you're right, your algorithm passes this test, it was my misunderstanding.
There is an algo working in O(500·(N + M)). Here is the idea.
The standard DP for this problem is d[i][j] = k = LCS of S[0..i] and T[0..j]. Let's swap the parameter and the value: g[i][k] = minimal j that LCS of S[0..i] and T[0..j] = k.
Then, g[i][k] = min(g[i-1][k], nextOcc[s[i]][g[i-1][k-1]]), where nextOcc[c][j] is the position of the first occurrence of c in T after position j.
What is LIS in your text? We have to find LCS — longest common subsequence. How to calculate g[i][k] faster than n^2? What is 500?
In this case k is 500. If you replace LIS with LCS in his text it should be valid. The transition state is also O(1), since g[i][k] only requires g[i-1][k] and g[i-1][k-1]. The definition of g[i][k] is just as stated above, just make sure you recognize which variables correspond to which.
It's a typo, LIS should be read as LCS (never write anything late at night).
The second parameter is a bound for the answer (500 in this exact problem).
I have not seen this constraint beacause it was in section "output format". And problem statement still unclear "Print the longest common subsequence, with length no greater than 500". What if length of actual LCS is greater than 500? can I print any common subsquence with length 500, or only subsequence of actual LCS?