import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.List ;
public class Main {
/**
* Holds information about a sub set
*
* @param <T> type of subset items
*/
private static class SubSet< T> {
List< T> items; // items of subset
int startIndex1; // start index in list 1
int endIndex1; // end index in list 1
int startIndex2; // start index in list 2
int endIndex2; // end index in list 2
}
/**
* Run main example.
*
* @param args arguments - none honored.
* @throws java.lang.Exception - in case of any error.
*/
// define 2 lists
List
< Integer
> list1
= Arrays .
asList ( 1 ,
2 ,
3 ,
4 ,
5 ,
6 ,
3 ,
2 ,
5 ,
6 ,
7 ,
3 ,
8 ) ; List
< Integer
> list2
= Arrays .
asList ( 2 ,
8 ,
7 ,
2 ,
3 ,
4 ,
5 ,
3 ,
2 ,
5 ,
1 ,
5 ) ;
// print the lists
System .
out .
println ( "First list: " + Arrays .
toString ( list1.
toArray ( ) ) ) ; System .
out .
println ( "Second list: " + Arrays .
toString ( list2.
toArray ( ) ) ) ;
// get largest sub set
SubSet< Integer> largest = getLargestSubSet( list1, list2) ;
if ( largest == null ) {
// nothing found
System .
out .
println ( "No subset found." ) ; } else {
// print info about subset
System .
out .
println ( "Largest subset: " + Arrays .
toString ( largest.
items .
toArray ( ) ) ) ;
if ( largest.startIndex1 > 0 ) {
List< Integer> beforeList1 = list1.subList ( 0 , largest.startIndex1 ) ;
System .
out .
println ( "Items before largest subset in first list: " + Arrays .
toString ( beforeList1.
toArray ( ) ) ) ; }
if ( largest.endIndex1 < list1.size ( ) - 1 ) {
List< Integer> afterList1 = list1.subList ( largest.endIndex1 + 1 , list1.size ( ) ) ;
System .
out .
println ( "Items after largest subset in first list: " + Arrays .
toString ( afterList1.
toArray ( ) ) ) ; }
if ( largest.startIndex2 > 0 ) {
List< Integer> beforeList2 = list2.subList ( 0 , largest.startIndex2 ) ;
System .
out .
println ( "Items before largest subset in second list: " + Arrays .
toString ( beforeList2.
toArray ( ) ) ) ; }
if ( largest.endIndex2 < list2.size ( ) - 1 ) {
List< Integer> afterList2 = list2.subList ( largest.endIndex2 + 1 , list2.size ( ) ) ;
System .
out .
println ( "Items after largest subset in second list: " + Arrays .
toString ( afterList2.
toArray ( ) ) ) ; }
}
}
/**
* Equality check for items.
*
* @param obj1 first item.
* @param obj2 second item.
* @param <T> item type.
* @return true if equal,false if not.
*/
private static < T> boolean areEqual( T obj1, T obj2) {
return obj1 == obj2; // naive comparison
}
/**
* Get largest subset (first occurrence) for given lists.
*
* @param list1 first list.
* @param list2 second list.
* @param <T> list item type.
* @return Largest sub sequence list, or empty list.
*/
private static < T> SubSet< T> getLargestSubSet( List< T> list1, List< T> list2) {
SubSet< T> output = null ;
for ( int i = 0 ; i < list1.size ( ) ; i++ ) {
for ( int j = 0 ; j < list2.size ( ) ; j++ ) {
// optimisation : exit early
if ( output
!= null && output.
items .
size ( ) > Math .
min ( list1.
size ( ) , list2.
size ( ) ) ) { return output;
}
if ( areEqual( list1.get ( i) , list2.get ( j) ) ) {
// inspect sub sequence from this (i,j) onwards
output = inspectSubSet( list1, list2, i, j, output) ;
}
}
}
return output;
}
/**
* For given starting indices, inspect if there is a larger subset, than given one.
*
* @param list1 first list.
* @param list2 second list.
* @param index1 first index.
* @param index2 second index.
* @param oldSubSet existing largest subset, for comparison.
* @param <T> list item type.
* @return larger subset, if found, else existing one is returned as is.
*/
private static < T> SubSet< T> inspectSubSet( List< T> list1, List< T> list2,
int index1, int index2, SubSet< T> oldSubSet) {
// new subset candidate
SubSet< T> newSubSet = new SubSet< T> ( ) ;
newSubSet.items = new ArrayList< T> ( ) ;
newSubSet.startIndex1 = index1;
newSubSet.endIndex1 = index1;
newSubSet.startIndex2 = index2;
newSubSet.endIndex2 = index2;
// keep building subset as subsequent items keep matching
do {
newSubSet.items .add ( list1.get ( index1) ) ;
newSubSet.endIndex1 = index1;
newSubSet.endIndex2 = index2;
index1++;
index2++;
} while ( index1 < list1.size ( ) && index2 < list2.size ( )
&& areEqual( list1.get ( index1) , list2.get ( index2) ) ) ;
// return first, larger or same.
if ( oldSubSet == null ) {
return newSubSet;
} else if ( newSubSet.items .size ( ) > oldSubSet.items .size ( ) ) {
return newSubSet;
} else {
return oldSubSet;
}
}
}
aW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQXJyYXlzOwppbXBvcnQgamF2YS51dGlsLkxpc3Q7CgpwdWJsaWMgY2xhc3MgTWFpbiB7CiAgICAvKioKICAgICAqIEhvbGRzIGluZm9ybWF0aW9uIGFib3V0IGEgc3ViIHNldAogICAgICoKICAgICAqIEBwYXJhbSA8VD4gdHlwZSBvZiBzdWJzZXQgaXRlbXMKICAgICAqLwogICAgcHJpdmF0ZSBzdGF0aWMgY2xhc3MgU3ViU2V0PFQ+IHsKICAgICAgICBMaXN0PFQ+IGl0ZW1zOyAvLyBpdGVtcyBvZiBzdWJzZXQKICAgICAgICBpbnQgc3RhcnRJbmRleDE7IC8vIHN0YXJ0IGluZGV4IGluIGxpc3QgMQogICAgICAgIGludCBlbmRJbmRleDE7IC8vIGVuZCBpbmRleCBpbiBsaXN0IDEKICAgICAgICBpbnQgc3RhcnRJbmRleDI7IC8vIHN0YXJ0IGluZGV4IGluIGxpc3QgMgogICAgICAgIGludCBlbmRJbmRleDI7IC8vIGVuZCBpbmRleCBpbiBsaXN0IDIKICAgIH0KCiAgICAvKioKICAgICAqIFJ1biBtYWluIGV4YW1wbGUuCiAgICAgKgogICAgICogQHBhcmFtIGFyZ3MgYXJndW1lbnRzIC0gbm9uZSBob25vcmVkLgogICAgICogQHRocm93cyBqYXZhLmxhbmcuRXhjZXB0aW9uIC0gaW4gY2FzZSBvZiBhbnkgZXJyb3IuCiAgICAgKi8KICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHRocm93cyBqYXZhLmxhbmcuRXhjZXB0aW9uIHsKICAgICAgICAvLyBkZWZpbmUgMiBsaXN0cwogICAgICAgIExpc3Q8SW50ZWdlcj4gbGlzdDEgPSBBcnJheXMuYXNMaXN0KDEsIDIsIDMsIDQsIDUsIDYsIDMsIDIsIDUsIDYsIDcsIDMsIDgpOwogICAgICAgIExpc3Q8SW50ZWdlcj4gbGlzdDIgPSBBcnJheXMuYXNMaXN0KDIsIDgsIDcsIDIsIDMsIDQsIDUsIDMsIDIsIDUsIDEsIDUpOwoKICAgICAgICAvLyBwcmludCB0aGUgbGlzdHMKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIkZpcnN0IGxpc3Q6ICIgKyBBcnJheXMudG9TdHJpbmcobGlzdDEudG9BcnJheSgpKSk7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJTZWNvbmQgbGlzdDogIiArIEFycmF5cy50b1N0cmluZyhsaXN0Mi50b0FycmF5KCkpKTsKCiAgICAgICAgLy8gZ2V0IGxhcmdlc3Qgc3ViIHNldAogICAgICAgIFN1YlNldDxJbnRlZ2VyPiBsYXJnZXN0ID0gZ2V0TGFyZ2VzdFN1YlNldChsaXN0MSwgbGlzdDIpOwoKCiAgICAgICAgaWYgKGxhcmdlc3QgPT0gbnVsbCkgewogICAgICAgICAgICAvLyBub3RoaW5nIGZvdW5kCiAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiTm8gc3Vic2V0IGZvdW5kLiIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIC8vIHByaW50IGluZm8gYWJvdXQgc3Vic2V0CgogICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIkxhcmdlc3Qgc3Vic2V0OiAiICsgQXJyYXlzLnRvU3RyaW5nKGxhcmdlc3QuaXRlbXMudG9BcnJheSgpKSk7CgogICAgICAgICAgICBpZiAobGFyZ2VzdC5zdGFydEluZGV4MSA+IDApIHsKICAgICAgICAgICAgICAgIExpc3Q8SW50ZWdlcj4gYmVmb3JlTGlzdDEgPSBsaXN0MS5zdWJMaXN0KDAsIGxhcmdlc3Quc3RhcnRJbmRleDEpOwogICAgICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJJdGVtcyBiZWZvcmUgbGFyZ2VzdCBzdWJzZXQgaW4gZmlyc3QgbGlzdDogIiAKICAgICAgICAgICAgICAgICAgICAgICAgKyBBcnJheXMudG9TdHJpbmcoYmVmb3JlTGlzdDEudG9BcnJheSgpKSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIChsYXJnZXN0LmVuZEluZGV4MSA8IGxpc3QxLnNpemUoKSAtIDEpIHsKICAgICAgICAgICAgICAgIExpc3Q8SW50ZWdlcj4gYWZ0ZXJMaXN0MSA9IGxpc3QxLnN1Ykxpc3QobGFyZ2VzdC5lbmRJbmRleDEgKyAxLCBsaXN0MS5zaXplKCkpOwogICAgICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJJdGVtcyBhZnRlciBsYXJnZXN0IHN1YnNldCBpbiBmaXJzdCBsaXN0OiAiIAogICAgICAgICAgICAgICAgICAgICAgICArIEFycmF5cy50b1N0cmluZyhhZnRlckxpc3QxLnRvQXJyYXkoKSkpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAobGFyZ2VzdC5zdGFydEluZGV4MiA+IDApIHsKICAgICAgICAgICAgICAgIExpc3Q8SW50ZWdlcj4gYmVmb3JlTGlzdDIgPSBsaXN0Mi5zdWJMaXN0KDAsIGxhcmdlc3Quc3RhcnRJbmRleDIpOwogICAgICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJJdGVtcyBiZWZvcmUgbGFyZ2VzdCBzdWJzZXQgaW4gc2Vjb25kIGxpc3Q6ICIgCiAgICAgICAgICAgICAgICAgICAgICAgICsgQXJyYXlzLnRvU3RyaW5nKGJlZm9yZUxpc3QyLnRvQXJyYXkoKSkpOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiAobGFyZ2VzdC5lbmRJbmRleDIgPCBsaXN0Mi5zaXplKCkgLSAxKSB7CiAgICAgICAgICAgICAgICBMaXN0PEludGVnZXI+IGFmdGVyTGlzdDIgPSBsaXN0Mi5zdWJMaXN0KGxhcmdlc3QuZW5kSW5kZXgyICsgMSwgbGlzdDIuc2l6ZSgpKTsKICAgICAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiSXRlbXMgYWZ0ZXIgbGFyZ2VzdCBzdWJzZXQgaW4gc2Vjb25kIGxpc3Q6ICIgCiAgICAgICAgICAgICAgICAgICAgICAgICsgQXJyYXlzLnRvU3RyaW5nKGFmdGVyTGlzdDIudG9BcnJheSgpKSk7CiAgICAgICAgICAgIH0KCiAgICAgICAgfQoKCiAgICB9CgogICAgLyoqCiAgICAgKiBFcXVhbGl0eSBjaGVjayBmb3IgaXRlbXMuCiAgICAgKgogICAgICogQHBhcmFtIG9iajEgZmlyc3QgaXRlbS4KICAgICAqIEBwYXJhbSBvYmoyIHNlY29uZCBpdGVtLgogICAgICogQHBhcmFtIDxUPiAgaXRlbSB0eXBlLgogICAgICogQHJldHVybiB0cnVlIGlmIGVxdWFsLGZhbHNlIGlmIG5vdC4KICAgICAqLwogICAgcHJpdmF0ZSBzdGF0aWMgPFQ+IGJvb2xlYW4gYXJlRXF1YWwoVCBvYmoxLCBUIG9iajIpIHsKICAgICAgICByZXR1cm4gb2JqMSA9PSBvYmoyOyAvLyBuYWl2ZSBjb21wYXJpc29uCiAgICB9CgogICAgLyoqCiAgICAgKiBHZXQgbGFyZ2VzdCBzdWJzZXQgKGZpcnN0IG9jY3VycmVuY2UpIGZvciBnaXZlbiBsaXN0cy4KICAgICAqCiAgICAgKiBAcGFyYW0gbGlzdDEgZmlyc3QgbGlzdC4KICAgICAqIEBwYXJhbSBsaXN0MiBzZWNvbmQgbGlzdC4KICAgICAqIEBwYXJhbSA8VD4gICBsaXN0IGl0ZW0gdHlwZS4KICAgICAqIEByZXR1cm4gTGFyZ2VzdCBzdWIgc2VxdWVuY2UgbGlzdCwgb3IgZW1wdHkgbGlzdC4KICAgICAqLwogICAgcHJpdmF0ZSBzdGF0aWMgPFQ+IFN1YlNldDxUPiBnZXRMYXJnZXN0U3ViU2V0KExpc3Q8VD4gbGlzdDEsIExpc3Q8VD4gbGlzdDIpIHsKICAgICAgICBTdWJTZXQ8VD4gb3V0cHV0ID0gbnVsbDsKCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBsaXN0MS5zaXplKCk7IGkrKykgewogICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IGxpc3QyLnNpemUoKTsgaisrKSB7CgogICAgICAgICAgICAgICAgLy8gb3B0aW1pc2F0aW9uIDogZXhpdCBlYXJseQogICAgICAgICAgICAgICAgaWYgKG91dHB1dCAhPSBudWxsICYmIG91dHB1dC5pdGVtcy5zaXplKCkgPiBNYXRoLm1pbihsaXN0MS5zaXplKCksIGxpc3QyLnNpemUoKSkpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0OwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIGlmIChhcmVFcXVhbChsaXN0MS5nZXQoaSksIGxpc3QyLmdldChqKSkpIHsKICAgICAgICAgICAgICAgICAgICAvLyBpbnNwZWN0IHN1YiBzZXF1ZW5jZSBmcm9tIHRoaXMgKGksaikgb253YXJkcwogICAgICAgICAgICAgICAgICAgIG91dHB1dCA9IGluc3BlY3RTdWJTZXQobGlzdDEsIGxpc3QyLCBpLCBqLCBvdXRwdXQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gb3V0cHV0OwogICAgfQoKICAgIC8qKgogICAgICogRm9yIGdpdmVuIHN0YXJ0aW5nIGluZGljZXMsIGluc3BlY3QgaWYgdGhlcmUgaXMgYSBsYXJnZXIgc3Vic2V0LCB0aGFuIGdpdmVuIG9uZS4KICAgICAqCiAgICAgKiBAcGFyYW0gbGlzdDEgICAgIGZpcnN0IGxpc3QuCiAgICAgKiBAcGFyYW0gbGlzdDIgICAgIHNlY29uZCBsaXN0LgogICAgICogQHBhcmFtIGluZGV4MSAgICBmaXJzdCBpbmRleC4KICAgICAqIEBwYXJhbSBpbmRleDIgICAgc2Vjb25kIGluZGV4LgogICAgICogQHBhcmFtIG9sZFN1YlNldCBleGlzdGluZyBsYXJnZXN0IHN1YnNldCwgZm9yIGNvbXBhcmlzb24uCiAgICAgKiBAcGFyYW0gPFQ+ICAgICAgIGxpc3QgaXRlbSB0eXBlLgogICAgICogQHJldHVybiBsYXJnZXIgc3Vic2V0LCBpZiBmb3VuZCwgZWxzZSBleGlzdGluZyBvbmUgaXMgcmV0dXJuZWQgYXMgaXMuCiAgICAgKi8KICAgIHByaXZhdGUgc3RhdGljIDxUPiBTdWJTZXQ8VD4gaW5zcGVjdFN1YlNldChMaXN0PFQ+IGxpc3QxLCBMaXN0PFQ+IGxpc3QyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludCBpbmRleDEsIGludCBpbmRleDIsIFN1YlNldDxUPiBvbGRTdWJTZXQpIHsKICAgICAgICAvLyBuZXcgc3Vic2V0IGNhbmRpZGF0ZQogICAgICAgIFN1YlNldDxUPiBuZXdTdWJTZXQgPSBuZXcgU3ViU2V0PFQ+KCk7CiAgICAgICAgbmV3U3ViU2V0Lml0ZW1zID0gbmV3IEFycmF5TGlzdDxUPigpOwogICAgICAgIG5ld1N1YlNldC5zdGFydEluZGV4MSA9IGluZGV4MTsKICAgICAgICBuZXdTdWJTZXQuZW5kSW5kZXgxID0gaW5kZXgxOwogICAgICAgIG5ld1N1YlNldC5zdGFydEluZGV4MiA9IGluZGV4MjsKICAgICAgICBuZXdTdWJTZXQuZW5kSW5kZXgyID0gaW5kZXgyOwoKICAgICAgICAvLyBrZWVwIGJ1aWxkaW5nIHN1YnNldCBhcyBzdWJzZXF1ZW50IGl0ZW1zIGtlZXAgbWF0Y2hpbmcKICAgICAgICBkbyB7CiAgICAgICAgICAgIG5ld1N1YlNldC5pdGVtcy5hZGQobGlzdDEuZ2V0KGluZGV4MSkpOwogICAgICAgICAgICBuZXdTdWJTZXQuZW5kSW5kZXgxID0gaW5kZXgxOwogICAgICAgICAgICBuZXdTdWJTZXQuZW5kSW5kZXgyID0gaW5kZXgyOwogICAgICAgICAgICBpbmRleDErKzsKICAgICAgICAgICAgaW5kZXgyKys7CiAgICAgICAgfSB3aGlsZSAoaW5kZXgxIDwgbGlzdDEuc2l6ZSgpICYmIGluZGV4MiA8IGxpc3QyLnNpemUoKQogICAgICAgICAgICAgICAgJiYgYXJlRXF1YWwobGlzdDEuZ2V0KGluZGV4MSksIGxpc3QyLmdldChpbmRleDIpKSk7CgogICAgICAgIC8vIHJldHVybiBmaXJzdCwgbGFyZ2VyIG9yIHNhbWUuCiAgICAgICAgaWYgKG9sZFN1YlNldCA9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiBuZXdTdWJTZXQ7CiAgICAgICAgfSBlbHNlIGlmIChuZXdTdWJTZXQuaXRlbXMuc2l6ZSgpID4gb2xkU3ViU2V0Lml0ZW1zLnNpemUoKSkgewogICAgICAgICAgICByZXR1cm4gbmV3U3ViU2V0OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHJldHVybiBvbGRTdWJTZXQ7CiAgICAgICAgfQogICAgfQoKfQ==
stdout
First list: [1, 2, 3, 4, 5, 6, 3, 2, 5, 6, 7, 3, 8]
Second list: [2, 8, 7, 2, 3, 4, 5, 3, 2, 5, 1, 5]
Largest subset: [2, 3, 4, 5]
Items before largest subset in first list: [1]
Items after largest subset in first list: [6, 3, 2, 5, 6, 7, 3, 8]
Items before largest subset in second list: [2, 8, 7]
Items after largest subset in second list: [3, 2, 5, 1, 5]