Advertisement
Guest User

Untitled

a guest
May 15th, 2012
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 10.81 KB | None | 0 0
  1. import java.util.Arrays;
  2.  
  3. class SuffixArray
  4. {
  5.    
  6.     /*
  7.      * Create the LCP array from the suffix array
  8.      * @param s the input array populated from 0..N-1, with available pos N
  9.      * @param sa the already-computed suffix array 0..N-1
  10.      * @param LCP the resulting LCP array 0..N-1
  11.      */
  12.     public static void makeLCPArray( int [ ] s, int [ ] sa, int [ ] LCP )
  13.     {
  14.         int N = sa.length;
  15.         int [ ] rank = new int[ N ];
  16.        
  17.         s[ N ] = -1;
  18.         for( int i = 0; i < N; i++ )
  19.             rank[ sa[ i ] ] = i;
  20.        
  21.         int h = 0;
  22.         for( int i = 0; i < N; i++ )
  23.             if( rank[ i ] > 0 )
  24.             {
  25.                 int j = sa[ rank[ i ] - 1 ];
  26.                
  27.                 while( s[ i + h ] == s[ j + h ] )
  28.                     h++;
  29.                
  30.                 LCP[ rank[ i ] ] = h;
  31.                 if( h > 0 )
  32.                     h--;
  33.             }
  34.     }
  35.    
  36.     /*
  37.      * Fill in the suffix array information for String str
  38.      * @param str the input String
  39.      * @param sa existing array to place the suffix array
  40.      */
  41.     public static void createSuffixArray( String str, int [ ] sa, int [ ] LCP )
  42.     {        
  43.         int N = str.length( );
  44.        
  45.         int [ ] s = new int[ N + 3 ];
  46.         int [ ] SA = new int[ N + 3 ];
  47.        
  48.         for( int i = 0; i < N; i++ )
  49.             s[ i ] = str.charAt( i );
  50.        
  51.         makeSuffixArray( s, SA, N, 256 );
  52.        
  53.         for( int i = 0; i < N; i++ )
  54.             sa[ i ] = SA[ i ];
  55.        
  56.         makeLCPArray( s, sa, LCP );
  57.     }
  58.    
  59.    
  60.     // find the suffix array SA of s[0..n-1] in {1..K}^n
  61.     // require s[n]=s[n+1]=s[n+2]=0, n>=2
  62.     public static void makeSuffixArray( int [ ] s, int [ ] SA, int n, int K )
  63.     {
  64.         int n0 = ( n + 2 ) / 3;
  65.         int n1 = ( n + 1 ) / 3;
  66.         int n2 = n / 3;
  67.         int t = n0 - n1;  // 1 iff n%3 == 1
  68.         int n12 = n1 + n2 + t;
  69.  
  70.         int [ ] s12  = new int[ n12 + 3 ];
  71.         int [ ] SA12 = new int[ n12 + 3 ];
  72.         int [ ] s0   = new int[ n0 ];
  73.         int [ ] SA0  = new int[ n0 ];
  74.        
  75.         // generate positions in s for items in s12
  76.         // the "+t" adds a dummy mod 1 suffix if n%3 == 1
  77.         // at that point, the size of s12 is n12
  78.         for( int i = 0, j = 0; i < n + t; i++ )
  79.             if( i % 3 != 0 )
  80.                 s12[ j++ ] = i;
  81.        
  82.         int K12 = assignNames( s, s12, SA12, n0, n12, K );
  83.  
  84.         computeS12( s12, SA12, n12, K12 );
  85.         computeS0( s, s0, SA0, SA12, n0, n12, K );
  86.         merge( s, s12, SA, SA0, SA12, n, n0, n12, t );
  87.     }
  88.    
  89.     // Assigns the new supercharacter names.
  90.     // At end of routine, SA will have indices into s, in sorted order
  91.     // and s12 will have new character names
  92.     // Returns the number of names assigned; note that if
  93.     // this value is the same as n12, then SA is a suffix array for s12.
  94.     private static int assignNames( int [ ] s, int [ ] s12, int [ ] SA12,
  95.                                    int n0, int n12, int K )
  96.     {
  97.            // radix sort the new character trios
  98.         radixPass( s12 , SA12, s, 2, n12, K );
  99.         radixPass( SA12, s12 , s, 1, n12, K );  
  100.         radixPass( s12 , SA12, s, 0, n12, K );
  101.  
  102.           // find lexicographic names of triples
  103.         int name = 0;
  104.         int c0 = -1, c1 = -1, c2 = -1;
  105.      
  106.         for( int i = 0; i < n12; i++ )
  107.         {
  108.             if( s[ SA12[ i ] ] != c0 || s[ SA12[ i ] + 1 ] != c1
  109.                                      || s[ SA12[ i ] + 2 ] != c2 )
  110.             {
  111.                 name++;
  112.                 c0 = s[ SA12[ i ] ];
  113.                 c1 = s[ SA12[ i ] + 1 ];
  114.                 c2 = s[ SA12[ i ] + 2 ];
  115.             }
  116.          
  117.             if( SA12[ i ] % 3 == 1 )
  118.                 s12[ SA12[ i ] / 3 ]      = name;
  119.             else
  120.                 s12[ SA12[ i ] / 3 + n0 ] = name;
  121.        }
  122.      
  123.        return name;
  124.     }
  125.    
  126.    
  127.     // stably sort in[0..n-1] with indices into s that has keys in 0..K
  128.     // into out[0..n-1]; sort is relative to offset into s
  129.     // uses counting radix sort
  130.     private static void radixPass( int [ ] in, int [ ] out, int [ ] s, int offset,
  131.                                   int n, int K )
  132.     {
  133.         int [ ] count = new int[ K + 2 ];            // counter array
  134.        
  135.         for( int i = 0; i < n; i++ )
  136.             count[ s[ in[ i ] + offset ] + 1 ]++;    // count occurences
  137.        
  138.         for( int i = 1; i <= K + 1; i++ )            // compute exclusive sums
  139.             count[ i ] += count[ i - 1 ];
  140.  
  141.         for( int i = 0; i < n; i++ )
  142.             out[ count[ s[ in[ i ] + offset ] ]++ ] = in[ i ];      // sort
  143.     }
  144.    
  145.     // stably sort in[0..n-1] with indices into s that has keys in 0..K
  146.     // into out[0..n-1]
  147.     // uses counting radix sort
  148.     private static void radixPass( int [ ] in, int [ ] out, int [ ] s, int n, int K )
  149.     {
  150.         radixPass( in, out, s, 0, n, K );
  151.     }
  152.    
  153.  
  154.     // Compute the suffix array for s12, placing result into SA12
  155.     private static void computeS12( int [ ] s12, int [ ] SA12, int n12, int K12 )
  156.     {
  157.         if( K12 == n12 ) // if unique names, don't need recursion
  158.             for( int i = 0; i < n12; i++ )
  159.                 SA12[ s12[i] - 1 ] = i;
  160.         else
  161.         {
  162.             makeSuffixArray( s12, SA12, n12, K12 );
  163.             // store unique names in s12 using the suffix array
  164.             for( int i = 0; i < n12; i++ )
  165.                 s12[ SA12[ i ] ] = i + 1;
  166.         }
  167.     }
  168.    
  169.     private static void computeS0( int [ ] s, int [ ] s0, int [ ] SA0, int [ ] SA12,
  170.                                int n0, int n12, int K )
  171.     {
  172.         for( int i = 0, j = 0; i < n12; i++ )
  173.             if( SA12[ i ] < n0 )
  174.                 s0[ j++ ] = 3 * SA12[ i ];
  175.        
  176.         radixPass( s0, SA0, s, n0, K );
  177.     }
  178.    
  179.    
  180.     // merge sorted SA0 suffixes and sorted SA12 suffixes
  181.     private static void merge( int [ ] s, int [ ] s12,
  182.                               int [ ] SA, int [ ] SA0, int [ ] SA12,
  183.                               int n, int n0, int n12, int t )
  184.     {      
  185.         int p = 0, k = 0;
  186.        
  187.         while( t != n12 && p != n0 )
  188.         {
  189.             int i = getIndexIntoS( SA12, t, n0 ); // S12
  190.             int j = SA0[ p ];                     // S0
  191.            
  192.             if( suffix12IsSmaller( s, s12, SA12, n0, i, j, t ) )
  193.             {
  194.                 SA[ k++ ] = i;
  195.                 t++;
  196.             }
  197.             else
  198.             {
  199.                 SA[ k++ ] = j;
  200.                 p++;
  201.             }  
  202.         }
  203.        
  204.        while( p < n0 )
  205.             SA[ k++ ] = SA0[ p++ ];
  206.        while( t < n12 )
  207.             SA[ k++ ] = getIndexIntoS( SA12, t++, n0 );
  208.     }
  209.    
  210.     private static int getIndexIntoS( int [ ] SA12, int t, int n0 )
  211.     {
  212.         if( SA12[ t ] < n0 )
  213.             return SA12[ t ] * 3 + 1;
  214.         else
  215.             return ( SA12[ t ] - n0 ) * 3 + 2;
  216.     }
  217.    
  218.     private static boolean leq( int a1, int a2, int b1, int b2 )
  219.       { return a1 < b1 || a1 == b1 && a2 <= b2; }
  220.    
  221.     private static boolean leq( int a1, int a2, int a3, int b1, int b2, int b3 )
  222.       { return a1 < b1 || a1 == b1 && leq( a2, a3,b2, b3 ); }
  223.    
  224.     private static boolean suffix12IsSmaller( int [ ] s, int [ ] s12, int [ ] SA12,
  225.                                              int n0, int i, int j, int t )
  226.     {
  227.         if( SA12[ t ] < n0 )  // s1 vs s0; can break tie after 1 character
  228.             return leq( s[ i ], s12[ SA12[ t ] + n0 ],
  229.                         s[ j ], s12[ j / 3 ] );
  230.         else                  // s2 vs s0; can break tie after 2 characters
  231.             return leq( s[ i ], s[ i + 1 ], s12[ SA12[ t ] - n0 + 1 ],
  232.                         s[ j ], s[ j + 1 ], s12[ j / 3 + n0 ] );
  233.     }
  234.  
  235.     public static void printV(int [ ]  a, String comment)
  236.     {
  237.         System.out.print( comment + ":" );
  238.         for (int x : a )
  239.             System.out.print( x + " " );
  240.  
  241.         System.out.println( );
  242.     }
  243.  
  244.     public static boolean isPermutation(int [ ] SA, int n)
  245.     {
  246.         boolean [ ] seen = new boolean [ n ];
  247.        
  248.         for( int i = 0; i < n; i++ )
  249.             seen[ i ] = false;
  250.        
  251.         for( int i = 0; i < n; i++ )
  252.             seen[ SA[ i ] ] = true;
  253.        
  254.         for( int i = 0; i < n; i++ )
  255.             if( !seen[ i ] )
  256.                 return false;
  257.        
  258.         return true;
  259.     }
  260.  
  261.     public static boolean sleq( int  [ ] s1, int start1, int [ ] s2, int start2 )
  262.     {
  263.         for( int i = start1, j = start2; ; i++, j++ )
  264.         {
  265.             if( s1[ i ] < s2[ j ] )
  266.                 return true;
  267.            
  268.             if( s1[ i ] > s2[ j ] )
  269.                 return false;
  270.         }
  271.     }
  272.  
  273.     // is SA a sorted suffix array for s?
  274.     public static boolean isSorted( int [ ] SA, int [ ] s, int n )
  275.     {
  276.         for( int i = 0; i < n-1; i++ )
  277.             if( !sleq( s, SA[ i ], s, SA[ i + 1 ] ) )
  278.                 return false;
  279.      
  280.         return true;  
  281.     }
  282.  
  283.  
  284.  
  285.     public static void assert0( boolean cond )
  286.     {
  287.         if( !cond )
  288.             throw new AssertionException( );
  289.     }
  290.  
  291.  
  292.     public static void  main( String [ ] args )
  293.     {
  294.         final String abr = "banana";
  295.         int [ ] sufarr = new int[ abr.length( ) ];
  296.         int [ ] LCP = new int[ abr.length( ) ];
  297.  
  298.         createSuffixArray( "banana", sufarr, LCP );
  299.        
  300.         for( int i = 0; i < abr.length( ); i++ )
  301.             System.out.println( i + " " + sufarr[ i ] + " " + LCP[ i ] );
  302.     }
  303.  
  304.  
  305.  
  306.     /*
  307.      * Returns the LCP for any two strings
  308.      */
  309.     public static int computeLCP( String s1, String s2 )
  310.     {
  311.         int i = 0;
  312.        
  313.         while( i < s1.length( ) && i < s2.length( ) && s1.charAt( i ) == s2.charAt( i ) )
  314.             i++;
  315.        
  316.         return i;
  317.     }
  318.  
  319.     /*
  320.      * Fill in the suffix array and LCP information for String str
  321.      * @param str the input String
  322.      * @param SA existing array to place the suffix array
  323.      * @param LCP existing array to place the LCP information
  324.      */
  325.     public static void createSuffixArraySlow( String str, int [ ] SA, int [ ] LCP )
  326.     {
  327.         if( SA.length != str.length( ) || LCP.length != str.length( ) )
  328.             throw new IllegalArgumentException( );
  329.        
  330.         int N = str.length( );
  331.        
  332.         String [ ] suffixes = new String[ N ];
  333.         for( int i = 0; i < N; i++ )
  334.             suffixes[ i ] = str.substring( i );
  335.        
  336.         Arrays.sort( suffixes );
  337.        
  338.         for( int i = 0; i < N; i++ )
  339.             SA[ i ] = N - suffixes[ i ].length( );
  340.        
  341.         LCP[ 0 ] = 0;
  342.         for( int i = 1; i < N; i++ )
  343.             LCP[ i ] = computeLCP( suffixes[ i - 1 ], suffixes[ i ] );
  344.     }
  345. }
  346.  
  347.  
  348. class AssertionException extends RuntimeException
  349. {
  350. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement