Given an array string, find the longest substring which is palindrome. For example, if the given string is “forgeeksskeegfor”, the output should be "geeksskeeg".
The problem has an efficient solution with Dynamic Programming.
However, I was just wondering why cant we solve the problem with Divide and Conquer in a similar way we solve the Maximum Subarray problem. (http://en.wikipedia.org/wiki/Maximum_subarray_problem )
We formulate the maximum subarray problem to be efficiently solved with D&C:
1) Divide the given array in two halves
2) Return the maximum of following three
….a) Maximum subarray sum in left half (Make a recursive call)
….b) Maximum subarray sum in right half (Make a recursive call)
….c) Maximum subarray sum such that the subarray crosses the midpoint
The longest Palindrome subsequence problem can be though of as :
1) Divide the given array in two halves
2) Return the maximum of following three
….a) Maximum palindrome sum in left half (Make a recursive call)
….b) Maximum palindrome sum in right half (Make a recursive call)
….c) Maximum palindrome sum such that the subarray crosses the midpoint
We could think about an implementation and say a solution does not exists,but what about the problem structure stops us from thinking a D&C solution?
The approach of Divide and Conquer might work if the string is of the form "13267224".
Here, 6+2+3 = 11 and 7+2+2 = 11
Hence, "326722" is the longest palindromic sum substring. But in the case of character strings eg. "abaccidba", Divide and Conquer won't work.
Related
Consider an array, which has N integers. Now we are given with an index i, which can take up values from 1 through N. This particular index should always be present in the LIS that we generate. Calculate the LIS for each value at i.
How can we solve the above problem efficiently? My straightforward solution is to vary the index i for all of its values and calculate LIS. The time complexity goes up to O(N2log(N)). Can it be beaten?
Example:
N = 2. i = 1
Say the given array is [1,2].
[1,2] or [2, 2]
The longest (strictly) increasing subsequence in each case is 2 and 1.
The canonical dynamic program for LIS computes, for each k, the longest increasing subsequence of the elements at index 1..k that includes the element at index k. Using this data and the mirror image data for longest increasing subsequences of k..n, we find the LIS that includes index k as the union of the longest before k and the longest after k.
O(n log n)
Having an index i that must be in the subsequence makes it an easy task to look to the left and right and see how far you can go to remain strictly increasing. This will take at most O(N) steps.
The straight forward solution will now just repeat this for all N values at the index i, which gives a total effort of O(N^2).
But note, that when changing the value at index i, the calculations done earlier can be reused. It is only necessary to check if the the sequence can be extended beyond i in either direction or not, If yes, you know already how far (or can calculate it now once and for all).
This brings the total effort down to O(N).
How to find the difference between the last and first element of the longest increasing sub-sequence such that value of (last element - first element) in LIS is maximum ?
Let's use a standard dynamic programming solution where we define f[i] as the longest increasing subsequence ending in the i-th element. We can store a pair (max length, smallest first element) for each i instead. One can show that it leads to a correct global solution (intuitively, it's correct as it still stores an optimal solution for all subsequences ending in a specific element and the fact that one prefix is "better" than the other means that the overall subsequence is better).
You can also make it O(N log N) by storing this pairs in an efficient data structure (like a segment tree) if the performance requirements are high.
Very naive algorithm is as follows:
In the first pass find all maximal consecutive subsequences and their length maintain the maximum length (just maintain the number for this).
In the second pass find the start and end differences of all sequences of maximum length and output the one which is maximum among all of them.
All this is in O (n), it is possible to do it in one pass. Just to simplify it I break it down into two steps.
If more than two subarrays exist we need to return the subarray that has lesser length.
We are only concerned with length of the subarray and its sum.
I know this can be solved in O(n^2) using brute force ,but i am looking for a efficient way to do this.
I also tried solving this in O(n) using the sliding window concept , but i later realized it fails for some cases.
How can this be done efficiently?
I would suggest you to look at Kadane's algorithm. It finds a contiguous subarray with the largest sum from a given array. It does so in O(n). Your problem restrains the length to "k". So you simply need to put a check for length <= k in Kadane's.
Last week in an interview I was asked the above question and as expected I wasn't able to answer it correctly, later on when I checked I saw that its a dynamic programming based algorithm. I am not proficient in dynamic programming but suppose I was to design this algorithm then how should I approach it?
Suppose, I take idea from other divide and conquer algorithms like MergeSort and design the solution something like:
Divide the sequence in two equal halves.
Find the longest increasing sub-sequence in two halves
Join the two halves.
Obviously there are missing pieces, but how get forward from here?
Your proposal won't work, because the longest sequences in both halves usually won't be contiguous, and there could exist a longer sequence when you join the halves.
You can fix this as follows:
in both halves, find the longest increasing sub-sequence, let L and R;
in both halves, find the longest increasing sub-sequence which is left-aligned, let LL and RL;
in both halves, find the longest increasing sub-sequence which is right-aligned, let LR and RR;
for the longest, keep the longest of L, R, LR+RL if the latter forms an increasing sequence;
for the left-aligned, keep LL or the whole left sub-sequence + RL if this forms an increasing sub-sequence;
for the right-aligned, keep RR or LR + the whole right sub-sequence if this forms an increasing sub-sequence.
All these operations are done in a single recursive process. When you concatenete two sub-sequences, checking if they form an increasing sub-sequence just takes the comparison of the facing elements.
Update:
This "fix" was not thoroughly checked.
I've seen some discussion about longest monotonically increasing sub-sequence algorithm. But my case is a little bit different.
The double increasing sub-sequence is defined as this:
The first part and second part of the sub-sequence are both monotonically increasing sub-sequences.
For example:
the sequence 10,19,8,12 is;
the sequence 10,19,28,33 is;
the sequence 10,19,28,28 is;
the sequence 10,19,8,2 not;
the sequence 10,19,8,8 not
another sequence that satisfy the condition is:
1,3,5,7,9,10, 6,9,11,17,28,30;
so the first part 1,3,5,7,9,10 is strictly monotonically increasing; and the same for the second part 6,9,11,17,28,30.
The original sequence maybe something like:
1,99,3,98,5,97,7,96,9,95,10, 6,89,9,88,11,87,17,86,28,85,30
Can we find a little-o(n^2)-time algorithm?
Yes, it is even possible to get an O(n log n) solution. Let's assume that we have computed the length of the longest increasing subsequence that ends somewhere to the left(inclusively) from i for each i and the length of the longest decreasing subsequence in a reversed array that to the right from i(not including i). Then the answer is the lagrest sum of these two values for all i. It can be done in O(n log n) time because all what you have to do is to run standard algorithm for computing the longest increasing/decreasing subsequence twice and then make a couple of linear passes.