//hold the LIS values for memoization
int * lisTable = NULL;
//hold the indexes stored as linked pointer , given the first index idx first value is arr[idx] , next value will be linked at
//lisIndex[idx] = idx1 , next value is arr[idx1] , the next is at index lisIndex[idx1] .. so on untill -1 is returned by lisIndex[] to mark end
int * lisIndex = NULL;
void initLisTable ( int n)
{
int i;
lisIndex
= ( int * ) malloc ( sizeof ( int ) * ( n
) ) ; lisTable
= ( int * ) malloc ( sizeof ( int ) * ( n
) ) ; lisTable[ 0 ] = 1 ; //holds the maximum length
//since lis(0) is of length one with element arr[0]s
lisIndex[ 0 ] = - 1 ;
for ( i = 1 ; i< n ; i++ )
{
lisTable[ i] = - 1 ;
lisIndex[ i] = - 1 ;
}
}
void printLisDetail ( int arr[ ] , int maxLen , int n)
{
int i;
//calculate the idx of lis stored in listable which corresponds to max in length
for ( i = 0 ; i < n ; i++ )
{
if ( lisTable[ i] == maxLen)
break ;
}
//start from this lis and print all the elements of this lis
while ( i != - 1 )
{
//get the next index of this lis from lisIndex table which maps to arr[]
i = lisIndex[ i] ;
}
}
int lis_DP ( int arr[ ] , int n, int * max)
{
int i, ret, max_val = - 1 , idx = - 1 ;
//if value exists in looktable return from there so that recursion is minimized
if ( lisTable[ n] >= 0 )
return lisTable[ n] ;
for ( i = 0 ; i < n ; i++ )
{
//calculate LIS for i = 0 to i n , and set the max length of LIS in max
// lis(i) = 1+max(lis(j)) j is -> 0 <= j <= i and for which arr[i] > arr[j] is true or 1 if no such j exist = 1
ret = lis_DP ( arr, i, max) ;
//if lis of this elment is > than the previous element then update overall max
if ( ret > max_val)
{
* max = ret;
//to calculate lis(n) if this satisfy second condition of equation above
//save it to max_val and idx for further processing and further checking with other less than n elements
if ( arr[ i] <= arr[ n] )
{
max_val = ret;
idx = i;
}
}
}
//if second condition of above holds true
if ( max_val == - 1 )
{
lisTable[ n] = 1 ;
// one element lis with only element = n , so index points to end
lisIndex[ n] = - 1 ;
}
else
{
lisTable[ n] = 1 + max_val;
//update the index of the lis(n) to max lis calculated , this recursivly points to the elements in arr[] using lisIndex[]
lisIndex[ n] = idx;
}
return lisTable[ n] ;
}
Ly9ob2xkIHRoZSBMSVMgdmFsdWVzIGZvciBtZW1vaXphdGlvbgppbnQgKmxpc1RhYmxlID0gTlVMTDsKLy9ob2xkIHRoZSBpbmRleGVzIHN0b3JlZCBhcyBsaW5rZWQgcG9pbnRlciAsIGdpdmVuIHRoZSBmaXJzdCBpbmRleCBpZHggZmlyc3QgdmFsdWUgaXMgYXJyW2lkeF0gLCBuZXh0IHZhbHVlIHdpbGwgYmUgbGlua2VkIGF0Ci8vbGlzSW5kZXhbaWR4XSA9IGlkeDEgLCBuZXh0IHZhbHVlIGlzIGFycltpZHgxXSAsIHRoZSBuZXh0IGlzIGF0IGluZGV4IGxpc0luZGV4W2lkeDFdIC4uIHNvIG9uIHVudGlsbCAtMSBpcyByZXR1cm5lZCBieSBsaXNJbmRleFtdIHRvIG1hcmsgZW5kCmludCAqbGlzSW5kZXggPSBOVUxMOwoKdm9pZCBpbml0TGlzVGFibGUgKGludCBuKQp7CglpbnQgaTsKCglsaXNJbmRleCA9IChpbnQqKSBtYWxsb2MgKHNpemVvZiAoaW50KSoobikpOwoJbGlzVGFibGUgPSAoaW50KikgbWFsbG9jIChzaXplb2YgKGludCkqKG4pKTsKCWxpc1RhYmxlWzBdID0gMTsvL2hvbGRzIHRoZSBtYXhpbXVtIGxlbmd0aAovL3NpbmNlIGxpcygwKSBpcyBvZiBsZW5ndGggb25lIHdpdGggZWxlbWVudCBhcnJbMF1zCglsaXNJbmRleFswXSA9IC0xOwoKCWZvciAoaSA9IDEgOyBpPG4gOyBpKyspCgl7CgkJbGlzVGFibGVbaV0gPSAtMTsKCQlsaXNJbmRleFtpXSA9IC0xOwoJfQp9Cgp2b2lkIHByaW50TGlzRGV0YWlsIChpbnQgYXJyW10saW50IG1heExlbiAsaW50IG4pCnsKCWludCBpOwoKCS8vY2FsY3VsYXRlIHRoZSBpZHggb2YgbGlzIHN0b3JlZCBpbiBsaXN0YWJsZSB3aGljaCBjb3JyZXNwb25kcyB0byBtYXggaW4gbGVuZ3RoCglmb3IgKCBpID0gMDsgaSA8IG4gOyBpKyspCgl7CgkJaWYgKGxpc1RhYmxlW2ldID09IG1heExlbikKCQkJYnJlYWs7Cgl9CglwcmludGYgKCJMaXMgZWxlbWVudHNcbiIpOwoKCS8vc3RhcnQgZnJvbSB0aGlzIGxpcyBhbmQgcHJpbnQgYWxsIHRoZSBlbGVtZW50cyBvZiB0aGlzIGxpcwoJd2hpbGUgKGkgIT0gLTEpCgl7CgkJcHJpbnRmICgiJWQgICAiLGFycltpXSk7CgkJLy9nZXQgdGhlIG5leHQgaW5kZXggb2YgdGhpcyBsaXMgZnJvbSBsaXNJbmRleCB0YWJsZSB3aGljaCBtYXBzIHRvIGFycltdCgkJaSA9IGxpc0luZGV4W2ldOwoJfQoJcHJpbnRmICgiXG4iKTsKfQoKaW50IGxpc19EUCAoaW50IGFycltdLCBpbnQgbiwgaW50ICogbWF4KQp7CglpbnQgaSwgcmV0LCBtYXhfdmFsID0gLTEgLCBpZHggID0gLTE7CgoJLy9pZiB2YWx1ZSBleGlzdHMgaW4gbG9va3RhYmxlIHJldHVybiBmcm9tIHRoZXJlIHNvIHRoYXQgcmVjdXJzaW9uIGlzIG1pbmltaXplZAoJaWYgKGxpc1RhYmxlW25dID49IDApCgkJcmV0dXJuIGxpc1RhYmxlW25dOwoKCWZvciAoaSA9IDAgOyBpIDwgbiA7IGkrKykKCXsKCQkvL2NhbGN1bGF0ZSBMSVMgZm9yIGkgPSAwIHRvIGkgbiAsIGFuZCBzZXQgdGhlIG1heCBsZW5ndGggb2YgTElTIGluIG1heAoJCS8vIGxpcyhpKSA9IDErbWF4KGxpcyhqKSkgIGogaXMgLT4gMCA8PSBqIDw9IGkgYW5kIGZvciB3aGljaCBhcnJbaV0gPiBhcnJbal0gaXMgdHJ1ZSBvciAxIGlmIG5vIHN1Y2ggaiBleGlzdAk9IDEKCgkJcmV0ID0gbGlzX0RQIChhcnIsIGksbWF4KTsKCQkvL2lmIGxpcyBvZiB0aGlzIGVsbWVudCBpcyA+IHRoYW4gdGhlIHByZXZpb3VzIGVsZW1lbnQgdGhlbiB1cGRhdGUgb3ZlcmFsbCBtYXgKCQlpZiAocmV0ID4gbWF4X3ZhbCkKCQl7CgkJCSptYXggPSByZXQ7CgkJCS8vdG8gY2FsY3VsYXRlIGxpcyhuKSBpZiB0aGlzIHNhdGlzZnkgc2Vjb25kIGNvbmRpdGlvbiBvZiBlcXVhdGlvbiBhYm92ZQoJCQkvL3NhdmUgaXQgdG8gbWF4X3ZhbCBhbmQgaWR4IGZvciBmdXJ0aGVyIHByb2Nlc3NpbmcgYW5kIGZ1cnRoZXIgY2hlY2tpbmcgd2l0aCBvdGhlciBsZXNzIHRoYW4gbiBlbGVtZW50cwoJCQlpZiAoYXJyW2ldIDw9IGFycltuXSkKCQkJewoJCQkJbWF4X3ZhbCA9IHJldDsKCQkJCWlkeCA9IGk7CgkJCX0KCQl9Cgl9CgoJLy9pZiBzZWNvbmQgY29uZGl0aW9uIG9mIGFib3ZlIGhvbGRzIHRydWUKCWlmIChtYXhfdmFsID09IC0xKQoJewoJCWxpc1RhYmxlW25dID0gMTsKCQkvLyBvbmUgZWxlbWVudCBsaXMgd2l0aCBvbmx5IGVsZW1lbnQgPSBuICwgc28gaW5kZXggcG9pbnRzIHRvIGVuZAoJCWxpc0luZGV4W25dID0gLTE7Cgl9CgllbHNlCgl7CgkJbGlzVGFibGVbbl0gPSAxICsgbWF4X3ZhbDsKCQkvL3VwZGF0ZSB0aGUgaW5kZXggb2YgdGhlIGxpcyhuKSB0byBtYXggbGlzIGNhbGN1bGF0ZWQgLCB0aGlzIHJlY3Vyc2l2bHkgcG9pbnRzIHRvIHRoZSBlbGVtZW50cyBpbiBhcnJbXSB1c2luZyBsaXNJbmRleFtdCgkJbGlzSW5kZXhbbl0gPSBpZHg7Cgl9CglyZXR1cm4gbGlzVGFibGVbbl07Cn0K