import java.io.BufferedReader ;
import java.io.IOException ;
import java.io.InputStreamReader ;
public class Main {
/*
* Create the LCP array from the suffix array
* @param s the input array populated from 0..N-1, with available pos N
* @param sa the already-computed suffix array 0..N-1
* @param LCP the resulting LCP array 0..N-1
*/
public static void makeLCPArray( int [ ] s, int [ ] sa, int [ ] LCP )
{
int N = sa.length ;
int [ ] rank = new int [ N ] ;
s[ N ] = - 1 ;
for ( int i = 0 ; i < N; i++ )
rank[ sa[ i ] ] = i;
int h = 0 ;
for ( int i = 0 ; i < N; i++ )
if ( rank[ i ] > 0 )
{
int j = sa[ rank[ i ] - 1 ] ;
while ( s[ i + h ] == s[ j + h ] )
h++;
LCP[ rank[ i ] ] = h;
if ( h > 0 )
h--;
}
}
/*
* Fill in the suffix array information for String str
* @param str the input String
* @param sa existing array to place the suffix array
*/
public static void createSuffixArray
( String str,
int [ ] sa,
int [ ] LCP
) {
int N = str.length ( ) ;
int [ ] s = new int [ N + 3 ] ;
int [ ] SA = new int [ N + 3 ] ;
for ( int i = 0 ; i < N; i++ )
s[ i ] = str.charAt ( i ) ;
makeSuffixArray( s, SA, N, 256 ) ;
for ( int i = 0 ; i < N; i++ )
sa[ i ] = SA[ i ] ;
makeLCPArray( s, sa, LCP ) ;
}
// find the suffix array SA of s[0..n-1] in {1..K}^n
// require s[n]=s[n+1]=s[n+2]=0, n>=2
public static void makeSuffixArray( int [ ] s, int [ ] SA, int n, int K )
{
int n0 = ( n + 2 ) / 3 ;
int n1 = ( n + 1 ) / 3 ;
int n2 = n / 3 ;
int t = n0 - n1; // 1 iff n%3 == 1
int n12 = n1 + n2 + t;
int [ ] s12 = new int [ n12 + 3 ] ;
int [ ] SA12 = new int [ n12 + 3 ] ;
int [ ] s0 = new int [ n0 ] ;
int [ ] SA0 = new int [ n0 ] ;
// generate positions in s for items in s12
// the "+t" adds a dummy mod 1 suffix if n%3 == 1
// at that point, the size of s12 is n12
for ( int i = 0 , j = 0 ; i < n + t; i++ )
if ( i % 3 != 0 )
s12[ j++ ] = i;
int K12 = assignNames( s, s12, SA12, n0, n12, K ) ;
computeS12( s12, SA12, n12, K12 ) ;
computeS0( s, s0, SA0, SA12, n0, n12, K ) ;
merge( s, s12, SA, SA0, SA12, n, n0, n12, t ) ;
}
// Assigns the new supercharacter names.
// At end of routine, SA will have indices into s, in sorted order
// and s12 will have new character names
// Returns the number of names assigned; note that if
// this value is the same as n12, then SA is a suffix array for s12.
private static int assignNames( int [ ] s, int [ ] s12, int [ ] SA12,
int n0, int n12, int K )
{
// radix sort the new character trios
radixPass( s12 , SA12, s, 2 , n12, K ) ;
radixPass( SA12, s12 , s, 1 , n12, K ) ;
radixPass( s12 , SA12, s, 0 , n12, K ) ;
// find lexicographic names of triples
int name = 0 ;
int c0 = - 1 , c1 = - 1 , c2 = - 1 ;
for ( int i = 0 ; i < n12; i++ )
{
if ( s[ SA12[ i ] ] != c0 || s[ SA12[ i ] + 1 ] != c1
|| s[ SA12[ i ] + 2 ] != c2 )
{
name++;
c0 = s[ SA12[ i ] ] ;
c1 = s[ SA12[ i ] + 1 ] ;
c2 = s[ SA12[ i ] + 2 ] ;
}
if ( SA12[ i ] % 3 == 1 )
s12[ SA12[ i ] / 3 ] = name;
else
s12[ SA12[ i ] / 3 + n0 ] = name;
}
return name;
}
// stably sort in[0..n-1] with indices into s that has keys in 0..K
// into out[0..n-1]; sort is relative to offset into s
// uses counting radix sort
private static void radixPass( int [ ] in, int [ ] out, int [ ] s, int offset,
int n, int K )
{
int [ ] count = new int [ K + 2 ] ; // counter array
for ( int i = 0 ; i < n; i++ )
count[ s[ in[ i ] + offset ] + 1 ] ++; // count occurences
for ( int i = 1 ; i <= K + 1 ; i++ ) // compute exclusive sums
count[ i ] += count[ i - 1 ] ;
for ( int i = 0 ; i < n; i++ )
out[ count[ s[ in[ i ] + offset ] ] ++ ] = in[ i ] ; // sort
}
// stably sort in[0..n-1] with indices into s that has keys in 0..K
// into out[0..n-1]
// uses counting radix sort
private static void radixPass( int [ ] in, int [ ] out, int [ ] s, int n, int K )
{
radixPass( in, out, s, 0 , n, K ) ;
}
// Compute the suffix array for s12, placing result into SA12
private static void computeS12( int [ ] s12, int [ ] SA12, int n12, int K12 )
{
if ( K12 == n12 ) // if unique names, don't need recursion
for ( int i = 0 ; i < n12; i++ )
SA12[ s12[ i] - 1 ] = i;
else
{
makeSuffixArray( s12, SA12, n12, K12 ) ;
// store unique names in s12 using the suffix array
for ( int i = 0 ; i < n12; i++ )
s12[ SA12[ i ] ] = i + 1 ;
}
}
private static void computeS0( int [ ] s, int [ ] s0, int [ ] SA0, int [ ] SA12,
int n0, int n12, int K )
{
for ( int i = 0 , j = 0 ; i < n12; i++ )
if ( SA12[ i ] < n0 )
s0[ j++ ] = 3 * SA12[ i ] ;
radixPass( s0, SA0, s, n0, K ) ;
}
// merge sorted SA0 suffixes and sorted SA12 suffixes
private static void merge( int [ ] s, int [ ] s12,
int [ ] SA, int [ ] SA0, int [ ] SA12,
int n, int n0, int n12, int t )
{
int p = 0 , k = 0 ;
while ( t != n12 && p != n0 )
{
int i = getIndexIntoS( SA12, t, n0 ) ; // S12
int j = SA0[ p ] ; // S0
if ( suffix12IsSmaller( s, s12, SA12, n0, i, j, t ) )
{
SA[ k++ ] = i;
t++;
}
else
{
SA[ k++ ] = j;
p++;
}
}
while ( p < n0 )
SA[ k++ ] = SA0[ p++ ] ;
while ( t < n12 )
SA[ k++ ] = getIndexIntoS( SA12, t++ , n0 ) ;
}
private static int getIndexIntoS( int [ ] SA12, int t, int n0 )
{
if ( SA12[ t ] < n0 )
return SA12[ t ] * 3 + 1 ;
else
return ( SA12[ t ] - n0 ) * 3 + 2 ;
}
private static boolean leq( int a1, int a2, int b1, int b2 )
{ return a1 < b1 || a1 == b1 && a2 <= b2; }
private static boolean leq( int a1, int a2, int a3, int b1, int b2, int b3 )
{ return a1 < b1 || a1 == b1 && leq( a2, a3,b2, b3 ) ; }
private static boolean suffix12IsSmaller( int [ ] s, int [ ] s12, int [ ] SA12,
int n0, int i, int j, int t )
{
if ( SA12[ t ] < n0 ) // s1 vs s0; can break tie after 1 character
return leq( s[ i ] , s12[ SA12[ t ] + n0 ] ,
s[ j ] , s12[ j / 3 ] ) ;
else // s2 vs s0; can break tie after 2 characters
return leq( s[ i ] , s[ i + 1 ] , s12[ SA12[ t ] - n0 + 1 ] ,
s[ j ] , s[ j + 1 ] , s12[ j / 3 + n0 ] ) ;
}
public static void printV
( int [ ] a,
String comment
) {
System .
out .
print ( comment
+ ":" ) ; for ( int x : a )
}
public static boolean isPermutation( int [ ] SA, int n )
{
boolean [ ] seen = new boolean [ n ] ;
for ( int i = 0 ; i < n; i++ )
seen[ i ] = false ;
for ( int i = 0 ; i < n; i++ )
seen[ SA[ i ] ] = true ;
for ( int i = 0 ; i < n; i++ )
if ( ! seen[ i ] )
return false ;
return true ;
}
public static boolean sleq( int [ ] s1, int start1, int [ ] s2, int start2 )
{
for ( int i = start1, j = start2; ; i++ , j++ )
{
if ( s1[ i ] < s2[ j ] )
return true ;
if ( s1[ i ] > s2[ j ] )
return false ;
}
}
// Check if SA is a sorted suffix array for s
public static boolean isSorted( int [ ] SA, int [ ] s, int n )
{
for ( int i = 0 ; i < n- 1 ; i++ )
if ( ! sleq( s, SA[ i ] , s, SA[ i + 1 ] ) )
return false ;
return true ;
}
int t
= Integer .
parseInt ( bf.
readLine ( ) ) ; while ( t--> 0 ) {
int n = s.length ( ) ;
int [ ] SA = new int [ n] ;
int [ ] LCP = new int [ n] ;
createSuffixArray( s, SA, LCP ) ;
int count = n - SA[ 0 ] ;
for ( int i = 1 ; i< n; i++ )
count += ( n - SA[ i] ) - LCP[ i] ;
}
}
}
aW1wb3J0IGphdmEuaW8uQnVmZmVyZWRSZWFkZXI7CmltcG9ydCBqYXZhLmlvLklPRXhjZXB0aW9uOwppbXBvcnQgamF2YS5pby5JbnB1dFN0cmVhbVJlYWRlcjsKIAogCnB1YmxpYyBjbGFzcyBNYWluIHsKCS8qCiAgICAgKiBDcmVhdGUgdGhlIExDUCBhcnJheSBmcm9tIHRoZSBzdWZmaXggYXJyYXkKICAgICAqIEBwYXJhbSBzIHRoZSBpbnB1dCBhcnJheSBwb3B1bGF0ZWQgZnJvbSAwLi5OLTEsIHdpdGggYXZhaWxhYmxlIHBvcyBOCiAgICAgKiBAcGFyYW0gc2EgdGhlIGFscmVhZHktY29tcHV0ZWQgc3VmZml4IGFycmF5IDAuLk4tMQogICAgICogQHBhcmFtIExDUCB0aGUgcmVzdWx0aW5nIExDUCBhcnJheSAwLi5OLTEKICAgICAqLwogICAgcHVibGljIHN0YXRpYyB2b2lkIG1ha2VMQ1BBcnJheSggaW50IFsgXSBzLCBpbnQgWyBdIHNhLCBpbnQgWyBdIExDUCApCiAgICB7CiAgICAgICAgaW50IE4gPSBzYS5sZW5ndGg7CiAgICAgICAgaW50IFsgXSByYW5rID0gbmV3IGludFsgTiBdOwogICAgICAgIAogICAgICAgIHNbIE4gXSA9IC0xOwogICAgICAgIGZvciggaW50IGkgPSAwOyBpIDwgTjsgaSsrICkKICAgICAgICAgICAgcmFua1sgc2FbIGkgXSBdID0gaTsKICAgICAgICAKICAgICAgICBpbnQgaCA9IDA7CiAgICAgICAgZm9yKCBpbnQgaSA9IDA7IGkgPCBOOyBpKysgKQogICAgICAgICAgICBpZiggcmFua1sgaSBdID4gMCApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGludCBqID0gc2FbIHJhbmtbIGkgXSAtIDEgXTsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgd2hpbGUoIHNbIGkgKyBoIF0gPT0gc1sgaiArIGggXSApCiAgICAgICAgICAgICAgICAgICAgaCsrOwogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBMQ1BbIHJhbmtbIGkgXSBdID0gaDsKICAgICAgICAgICAgICAgIGlmKCBoID4gMCApCiAgICAgICAgICAgICAgICAgICAgaC0tOwogICAgICAgICAgICB9CiAgICB9CiAgICAKICAgIC8qCiAgICAgKiBGaWxsIGluIHRoZSBzdWZmaXggYXJyYXkgaW5mb3JtYXRpb24gZm9yIFN0cmluZyBzdHIKICAgICAqIEBwYXJhbSBzdHIgdGhlIGlucHV0IFN0cmluZwogICAgICogQHBhcmFtIHNhIGV4aXN0aW5nIGFycmF5IHRvIHBsYWNlIHRoZSBzdWZmaXggYXJyYXkKICAgICAqLwogICAgcHVibGljIHN0YXRpYyB2b2lkIGNyZWF0ZVN1ZmZpeEFycmF5KCBTdHJpbmcgc3RyLCBpbnQgWyBdIHNhLCBpbnQgWyBdIExDUCApCiAgICB7ICAgICAgICAKICAgICAgICBpbnQgTiA9IHN0ci5sZW5ndGgoICk7CiAgICAgICAgCiAgICAgICAgaW50IFsgXSBzID0gbmV3IGludFsgTiArIDMgXTsKICAgICAgICBpbnQgWyBdIFNBID0gbmV3IGludFsgTiArIDMgXTsKICAgICAgICAKICAgICAgICBmb3IoIGludCBpID0gMDsgaSA8IE47IGkrKyApCiAgICAgICAgICAgIHNbIGkgXSA9IHN0ci5jaGFyQXQoIGkgKTsKICAgICAgICAKICAgICAgICBtYWtlU3VmZml4QXJyYXkoIHMsIFNBLCBOLCAyNTYgKTsKICAgICAgICAKICAgICAgICBmb3IoIGludCBpID0gMDsgaSA8IE47IGkrKyApCiAgICAgICAgICAgIHNhWyBpIF0gPSBTQVsgaSBdOwogICAgICAgIAogICAgICAgIG1ha2VMQ1BBcnJheSggcywgc2EsIExDUCApOwogICAgfQogICAgCiAgICAKICAgIC8vIGZpbmQgdGhlIHN1ZmZpeCBhcnJheSBTQSBvZiBzWzAuLm4tMV0gaW4gezEuLkt9Xm4KICAgIC8vIHJlcXVpcmUgc1tuXT1zW24rMV09c1tuKzJdPTAsIG4+PTIKICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWtlU3VmZml4QXJyYXkoIGludCBbIF0gcywgaW50IFsgXSBTQSwgaW50IG4sIGludCBLICkKICAgIHsKICAgICAgICBpbnQgbjAgPSAoIG4gKyAyICkgLyAzOwogICAgICAgIGludCBuMSA9ICggbiArIDEgKSAvIDM7CiAgICAgICAgaW50IG4yID0gbiAvIDM7CiAgICAgICAgaW50IHQgPSBuMCAtIG4xOyAgLy8gMSBpZmYgbiUzID09IDEKICAgICAgICBpbnQgbjEyID0gbjEgKyBuMiArIHQ7CiAKICAgICAgICBpbnQgWyBdIHMxMiAgPSBuZXcgaW50WyBuMTIgKyAzIF07CiAgICAgICAgaW50IFsgXSBTQTEyID0gbmV3IGludFsgbjEyICsgMyBdOwogICAgICAgIGludCBbIF0gczAgICA9IG5ldyBpbnRbIG4wIF07CiAgICAgICAgaW50IFsgXSBTQTAgID0gbmV3IGludFsgbjAgXTsKICAgICAgICAKICAgICAgICAvLyBnZW5lcmF0ZSBwb3NpdGlvbnMgaW4gcyBmb3IgaXRlbXMgaW4gczEyCiAgICAgICAgLy8gdGhlICIrdCIgYWRkcyBhIGR1bW15IG1vZCAxIHN1ZmZpeCBpZiBuJTMgPT0gMQogICAgICAgIC8vIGF0IHRoYXQgcG9pbnQsIHRoZSBzaXplIG9mIHMxMiBpcyBuMTIKICAgICAgICBmb3IoIGludCBpID0gMCwgaiA9IDA7IGkgPCBuICsgdDsgaSsrICkKICAgICAgICAgICAgaWYoIGkgJSAzICE9IDAgKQogICAgICAgICAgICAgICAgczEyWyBqKysgXSA9IGk7CiAgICAgICAgCiAgICAgICAgaW50IEsxMiA9IGFzc2lnbk5hbWVzKCBzLCBzMTIsIFNBMTIsIG4wLCBuMTIsIEsgKTsKICAKICAgICAgICBjb21wdXRlUzEyKCBzMTIsIFNBMTIsIG4xMiwgSzEyICk7CiAgICAgICAgY29tcHV0ZVMwKCBzLCBzMCwgU0EwLCBTQTEyLCBuMCwgbjEyLCBLICk7CiAgICAgICAgbWVyZ2UoIHMsIHMxMiwgU0EsIFNBMCwgU0ExMiwgbiwgbjAsIG4xMiwgdCApOwogICAgfQogICAgCiAgICAvLyBBc3NpZ25zIHRoZSBuZXcgc3VwZXJjaGFyYWN0ZXIgbmFtZXMuCiAgICAvLyBBdCBlbmQgb2Ygcm91dGluZSwgU0Egd2lsbCBoYXZlIGluZGljZXMgaW50byBzLCBpbiBzb3J0ZWQgb3JkZXIKICAgIC8vIGFuZCBzMTIgd2lsbCBoYXZlIG5ldyBjaGFyYWN0ZXIgbmFtZXMKICAgIC8vIFJldHVybnMgdGhlIG51bWJlciBvZiBuYW1lcyBhc3NpZ25lZDsgbm90ZSB0aGF0IGlmCiAgICAvLyB0aGlzIHZhbHVlIGlzIHRoZSBzYW1lIGFzIG4xMiwgdGhlbiBTQSBpcyBhIHN1ZmZpeCBhcnJheSBmb3IgczEyLgogICAgcHJpdmF0ZSBzdGF0aWMgaW50IGFzc2lnbk5hbWVzKCBpbnQgWyBdIHMsIGludCBbIF0gczEyLCBpbnQgWyBdIFNBMTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50IG4wLCBpbnQgbjEyLCBpbnQgSyApCiAgICB7CiAgICAgICAgICAgLy8gcmFkaXggc29ydCB0aGUgbmV3IGNoYXJhY3RlciB0cmlvcwogICAgICAgIHJhZGl4UGFzcyggczEyICwgU0ExMiwgcywgMiwgbjEyLCBLICk7CiAgICAgICAgcmFkaXhQYXNzKCBTQTEyLCBzMTIgLCBzLCAxLCBuMTIsIEsgKTsgIAogICAgICAgIHJhZGl4UGFzcyggczEyICwgU0ExMiwgcywgMCwgbjEyLCBLICk7CiAKICAgICAgICAgIC8vIGZpbmQgbGV4aWNvZ3JhcGhpYyBuYW1lcyBvZiB0cmlwbGVzCiAgICAgICAgaW50IG5hbWUgPSAwOwogICAgICAgIGludCBjMCA9IC0xLCBjMSA9IC0xLCBjMiA9IC0xOwogICAgICAKICAgICAgICBmb3IoIGludCBpID0gMDsgaSA8IG4xMjsgaSsrICkKICAgICAgICB7CiAgICAgICAgICAgIGlmKCBzWyBTQTEyWyBpIF0gXSAhPSBjMCB8fCBzWyBTQTEyWyBpIF0gKyAxIF0gIT0gYzEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHx8IHNbIFNBMTJbIGkgXSArIDIgXSAhPSBjMiApCiAgICAgICAgICAgIHsgCiAgICAgICAgICAgICAgICBuYW1lKys7CiAgICAgICAgICAgICAgICBjMCA9IHNbIFNBMTJbIGkgXSBdOwogICAgICAgICAgICAgICAgYzEgPSBzWyBTQTEyWyBpIF0gKyAxIF07CiAgICAgICAgICAgICAgICBjMiA9IHNbIFNBMTJbIGkgXSArIDIgXTsKICAgICAgICAgICAgfQogICAgICAgICAgCiAgICAgICAgICAgIGlmKCBTQTEyWyBpIF0gJSAzID09IDEgKQogICAgICAgICAgICAgICAgczEyWyBTQTEyWyBpIF0gLyAzIF0gICAgICA9IG5hbWU7CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIHMxMlsgU0ExMlsgaSBdIC8gMyArIG4wIF0gPSBuYW1lOyAKICAgICAgIH0KICAgICAgCiAgICAgICByZXR1cm4gbmFtZTsKICAgIH0KICAgIAogICAgCiAgICAvLyBzdGFibHkgc29ydCBpblswLi5uLTFdIHdpdGggaW5kaWNlcyBpbnRvIHMgdGhhdCBoYXMga2V5cyBpbiAwLi5LCiAgICAvLyBpbnRvIG91dFswLi5uLTFdOyBzb3J0IGlzIHJlbGF0aXZlIHRvIG9mZnNldCBpbnRvIHMKICAgIC8vIHVzZXMgY291bnRpbmcgcmFkaXggc29ydAogICAgcHJpdmF0ZSBzdGF0aWMgdm9pZCByYWRpeFBhc3MoIGludCBbIF0gaW4sIGludCBbIF0gb3V0LCBpbnQgWyBdIHMsIGludCBvZmZzZXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnQgbiwgaW50IEsgKSAKICAgIHsgCiAgICAgICAgaW50IFsgXSBjb3VudCA9IG5ldyBpbnRbIEsgKyAyIF07ICAgICAgICAgICAgLy8gY291bnRlciBhcnJheQogICAgICAgIAogICAgICAgIGZvciggaW50IGkgPSAwOyBpIDwgbjsgaSsrICkKICAgICAgICAgICAgY291bnRbIHNbIGluWyBpIF0gKyBvZmZzZXQgXSArIDEgXSsrOyAgICAvLyBjb3VudCBvY2N1cmVuY2VzCiAgICAgICAgCiAgICAgICAgZm9yKCBpbnQgaSA9IDE7IGkgPD0gSyArIDE7IGkrKyApICAgICAgICAgICAgLy8gY29tcHV0ZSBleGNsdXNpdmUgc3VtcwogICAgICAgICAgICBjb3VudFsgaSBdICs9IGNvdW50WyBpIC0gMSBdOwogCiAgICAgICAgZm9yKCBpbnQgaSA9IDA7IGkgPCBuOyBpKysgKQogICAgICAgICAgICBvdXRbIGNvdW50WyBzWyBpblsgaSBdICsgb2Zmc2V0IF0gXSsrIF0gPSBpblsgaSBdOyAgICAgIC8vIHNvcnQKICAgIH0gCiAgICAKICAgIC8vIHN0YWJseSBzb3J0IGluWzAuLm4tMV0gd2l0aCBpbmRpY2VzIGludG8gcyB0aGF0IGhhcyBrZXlzIGluIDAuLksKICAgIC8vIGludG8gb3V0WzAuLm4tMV0KICAgIC8vIHVzZXMgY291bnRpbmcgcmFkaXggc29ydAogICAgcHJpdmF0ZSBzdGF0aWMgdm9pZCByYWRpeFBhc3MoIGludCBbIF0gaW4sIGludCBbIF0gb3V0LCBpbnQgWyBdIHMsIGludCBuLCBpbnQgSyApIAogICAgeyAKICAgICAgICByYWRpeFBhc3MoIGluLCBvdXQsIHMsIDAsIG4sIEsgKTsKICAgIH0KICAgCiAKICAgIC8vIENvbXB1dGUgdGhlIHN1ZmZpeCBhcnJheSBmb3IgczEyLCBwbGFjaW5nIHJlc3VsdCBpbnRvIFNBMTIKICAgIHByaXZhdGUgc3RhdGljIHZvaWQgY29tcHV0ZVMxMiggaW50IFsgXSBzMTIsIGludCBbIF0gU0ExMiwgaW50IG4xMiwgaW50IEsxMiApCiAgICB7CiAgICAgICAgaWYoIEsxMiA9PSBuMTIgKSAvLyBpZiB1bmlxdWUgbmFtZXMsIGRvbid0IG5lZWQgcmVjdXJzaW9uCiAgICAgICAgICAgIGZvciggaW50IGkgPSAwOyBpIDwgbjEyOyBpKysgKQogICAgICAgICAgICAgICAgU0ExMlsgczEyW2ldIC0gMSBdID0gaTsgCiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgICAgbWFrZVN1ZmZpeEFycmF5KCBzMTIsIFNBMTIsIG4xMiwgSzEyICk7CiAgICAgICAgICAgIC8vIHN0b3JlIHVuaXF1ZSBuYW1lcyBpbiBzMTIgdXNpbmcgdGhlIHN1ZmZpeCBhcnJheSAKICAgICAgICAgICAgZm9yKCBpbnQgaSA9IDA7IGkgPCBuMTI7IGkrKyApCiAgICAgICAgICAgICAgICBzMTJbIFNBMTJbIGkgXSBdID0gaSArIDE7CiAgICAgICAgfQogICAgfQogICAgCiAgICBwcml2YXRlIHN0YXRpYyB2b2lkIGNvbXB1dGVTMCggaW50IFsgXSBzLCBpbnQgWyBdIHMwLCBpbnQgWyBdIFNBMCwgaW50IFsgXSBTQTEyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50IG4wLCBpbnQgbjEyLCBpbnQgSyApCiAgICB7CiAgICAgICAgZm9yKCBpbnQgaSA9IDAsIGogPSAwOyBpIDwgbjEyOyBpKysgKQogICAgICAgICAgICBpZiggU0ExMlsgaSBdIDwgbjAgKQogICAgICAgICAgICAgICAgczBbIGorKyBdID0gMyAqIFNBMTJbIGkgXTsKICAgICAgICAKICAgICAgICByYWRpeFBhc3MoIHMwLCBTQTAsIHMsIG4wLCBLICk7CiAgICB9CiAgICAKICAgIAogICAgLy8gbWVyZ2Ugc29ydGVkIFNBMCBzdWZmaXhlcyBhbmQgc29ydGVkIFNBMTIgc3VmZml4ZXMKICAgIHByaXZhdGUgc3RhdGljIHZvaWQgbWVyZ2UoIGludCBbIF0gcywgaW50IFsgXSBzMTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludCBbIF0gU0EsIGludCBbIF0gU0EwLCBpbnQgWyBdIFNBMTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludCBuLCBpbnQgbjAsIGludCBuMTIsIGludCB0ICkKICAgIHsgICAgICAKICAgICAgICBpbnQgcCA9IDAsIGsgPSAwOwogICAgICAgIAogICAgICAgIHdoaWxlKCB0ICE9IG4xMiAmJiBwICE9IG4wICkKICAgICAgICB7CiAgICAgICAgICAgIGludCBpID0gZ2V0SW5kZXhJbnRvUyggU0ExMiwgdCwgbjAgKTsgLy8gUzEyCiAgICAgICAgICAgIGludCBqID0gU0EwWyBwIF07ICAgICAgICAgICAgICAgICAgICAgLy8gUzAKICAgICAgICAgICAgCiAgICAgICAgICAgIGlmKCBzdWZmaXgxMklzU21hbGxlciggcywgczEyLCBTQTEyLCBuMCwgaSwgaiwgdCApICkKICAgICAgICAgICAgeyAKICAgICAgICAgICAgICAgIFNBWyBrKysgXSA9IGk7CiAgICAgICAgICAgICAgICB0Kys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZQogICAgICAgICAgICB7IAogICAgICAgICAgICAgICAgU0FbIGsrKyBdID0gajsKICAgICAgICAgICAgICAgIHArKzsKICAgICAgICAgICAgfSAgCiAgICAgICAgfSAKICAgICAgICAKICAgICAgICB3aGlsZSggcCA8IG4wICkKICAgICAgICAgICAgU0FbIGsrKyBdID0gU0EwWyBwKysgXTsKICAgICAgICB3aGlsZSggdCA8IG4xMiApCiAgICAgICAgICAgIFNBWyBrKysgXSA9IGdldEluZGV4SW50b1MoIFNBMTIsIHQrKywgbjAgKTsgCiAgICB9CiAgICAKICAgIHByaXZhdGUgc3RhdGljIGludCBnZXRJbmRleEludG9TKCBpbnQgWyBdIFNBMTIsIGludCB0LCBpbnQgbjAgKQogICAgewogICAgICAgIGlmKCBTQTEyWyB0IF0gPCBuMCApCiAgICAgICAgICAgIHJldHVybiBTQTEyWyB0IF0gKiAzICsgMTsKICAgICAgICBlbHNlCiAgICAgICAgICAgIHJldHVybiAoIFNBMTJbIHQgXSAtIG4wICkgKiAzICsgMjsKICAgIH0KICAgIAogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBsZXEoIGludCBhMSwgaW50IGEyLCBpbnQgYjEsIGludCBiMiApCiAgICAgIHsgcmV0dXJuIGExIDwgYjEgfHwgYTEgPT0gYjEgJiYgYTIgPD0gYjI7IH0KICAgIAogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBsZXEoIGludCBhMSwgaW50IGEyLCBpbnQgYTMsIGludCBiMSwgaW50IGIyLCBpbnQgYjMgKQogICAgICB7IHJldHVybiBhMSA8IGIxIHx8IGExID09IGIxICYmIGxlcSggYTIsIGEzLGIyLCBiMyApOyB9CiAgICAKICAgIHByaXZhdGUgc3RhdGljIGJvb2xlYW4gc3VmZml4MTJJc1NtYWxsZXIoIGludCBbIF0gcywgaW50IFsgXSBzMTIsIGludCBbIF0gU0ExMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50IG4wLCBpbnQgaSwgaW50IGosIGludCB0ICkKICAgIHsKICAgICAgICBpZiggU0ExMlsgdCBdIDwgbjAgKSAgLy8gczEgdnMgczA7IGNhbiBicmVhayB0aWUgYWZ0ZXIgMSBjaGFyYWN0ZXIKICAgICAgICAgICAgcmV0dXJuIGxlcSggc1sgaSBdLCBzMTJbIFNBMTJbIHQgXSArIG4wIF0sCiAgICAgICAgICAgICAgICAgICAgICAgIHNbIGogXSwgczEyWyBqIC8gMyBdICk7CiAgICAgICAgZWxzZSAgICAgICAgICAgICAgICAgIC8vIHMyIHZzIHMwOyBjYW4gYnJlYWsgdGllIGFmdGVyIDIgY2hhcmFjdGVycwogICAgICAgICAgICByZXR1cm4gbGVxKCBzWyBpIF0sIHNbIGkgKyAxIF0sIHMxMlsgU0ExMlsgdCBdIC0gbjAgKyAxIF0sCiAgICAgICAgICAgICAgICAgICAgICAgIHNbIGogXSwgc1sgaiArIDEgXSwgczEyWyBqIC8gMyArIG4wIF0gKTsKICAgIH0KIAogICAgcHVibGljIHN0YXRpYyB2b2lkIHByaW50ViggaW50IFsgXSAgYSwgU3RyaW5nIGNvbW1lbnQgKQogICAgewogICAgICAgIFN5c3RlbS5vdXQucHJpbnQoIGNvbW1lbnQgKyAiOiIgKTsKICAgICAgICBmb3IoIGludCB4IDogYSApIAogICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50KCB4ICsgIiAiICk7CiAKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oICk7CiAgICB9CiAKICAgIHB1YmxpYyBzdGF0aWMgYm9vbGVhbiBpc1Blcm11dGF0aW9uKCBpbnQgWyBdIFNBLCBpbnQgbiApCiAgICB7CiAgICAgICAgYm9vbGVhbiBbIF0gc2VlbiA9IG5ldyBib29sZWFuIFsgbiBdOwogICAgICAgIAogICAgICAgIGZvciggaW50IGkgPSAwOyBpIDwgbjsgaSsrICkKICAgICAgICAgICAgc2VlblsgaSBdID0gZmFsc2U7CiAgICAgICAgCiAgICAgICAgZm9yKCBpbnQgaSA9IDA7IGkgPCBuOyBpKysgKQogICAgICAgICAgICBzZWVuWyBTQVsgaSBdIF0gPSB0cnVlOwogICAgICAgIAogICAgICAgIGZvciggaW50IGkgPSAwOyBpIDwgbjsgaSsrICkKICAgICAgICAgICAgaWYoICFzZWVuWyBpIF0gKQogICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIAogICAgICAgIHJldHVybiB0cnVlOwogICAgfQogCiAgICBwdWJsaWMgc3RhdGljIGJvb2xlYW4gc2xlcSggaW50ICBbIF0gczEsIGludCBzdGFydDEsIGludCBbIF0gczIsIGludCBzdGFydDIgKQogICAgewogICAgICAgIGZvciggaW50IGkgPSBzdGFydDEsIGogPSBzdGFydDI7IDsgaSsrLCBqKysgKQogICAgICAgIHsKICAgICAgICAgICAgaWYoIHMxWyBpIF0gPCBzMlsgaiBdICkKICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAKICAgICAgICAgICAgaWYoIHMxWyBpIF0gPiBzMlsgaiBdICkKICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICB9IAogCiAgICAvLyBDaGVjayBpZiBTQSBpcyBhIHNvcnRlZCBzdWZmaXggYXJyYXkgZm9yIHMKICAgIHB1YmxpYyBzdGF0aWMgYm9vbGVhbiBpc1NvcnRlZCggaW50IFsgXSBTQSwgaW50IFsgXSBzLCBpbnQgbiApCiAgICB7CiAgICAgICAgZm9yKCBpbnQgaSA9IDA7IGkgPCBuLTE7IGkrKyApCiAgICAgICAgICAgIGlmKCAhc2xlcSggcywgU0FbIGkgXSwgcywgU0FbIGkgKyAxIF0gKSApCiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIAogICAgICAgIHJldHVybiB0cnVlOyAgCiAgICB9CiAKICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHRocm93cyBOdW1iZXJGb3JtYXRFeGNlcHRpb24sIElPRXhjZXB0aW9uIHsKICAgIAlCdWZmZXJlZFJlYWRlciBiZiA9IG5ldyBCdWZmZXJlZFJlYWRlcihuZXcgSW5wdXRTdHJlYW1SZWFkZXIoU3lzdGVtLmluKSk7CgkJIGludCB0ID0gSW50ZWdlci5wYXJzZUludChiZi5yZWFkTGluZSgpKTsKCQkgd2hpbGUodC0tPjApewoJCQkgU3RyaW5nIHMgPSBiZi5yZWFkTGluZSgpOwoJCQkgaW50IG4gPSBzLmxlbmd0aCgpOwoJCQkgaW50W10gU0EgPSBuZXcgaW50W25dOwoJCQkgaW50W10gTENQID0gbmV3IGludFtuXTsKCQkJIGNyZWF0ZVN1ZmZpeEFycmF5KCBzLCBTQSwgTENQICk7CgkJCSAKCQkJIGludCBjb3VudCA9IG4gLSBTQVswXTsKCQkJICAgIAoJCQkgZm9yKGludCBpID0gMTtpPG47aSsrKQoJCQkgICAgCWNvdW50ICs9IChuIC0gU0FbaV0pIC0gTENQW2ldOwoJCQkgICAKCQkJIFN5c3RlbS5vdXQucHJpbnRsbihjb3VudCk7CgkJIH0KCX0KfQ==