SPOJ-1811. Longest Common Substring && 1812. Longest Common Substring II (后缀自动机)

题目:

http://www.spoj.com/problems/LCS/

http://www.spoj.com/problems/LCS2/

两道水题,据说SA之类的常数卡得挺紧的,于是乎顺手拿过来练手了一下SAM。。。

代码:

1811:

#include <cstdio>
#include <algorithm>
#include <cstring>
 
using namespace std ;
 
#define C( t , x ) sam[ t ].ch[ x ]
#define P( t ) sam[ t ].parent
#define L( t ) sam[ t ].len
#define N( t ) sam[ t ]
 
#define check( ch ) ( ch >= 'a' && ch <= 'z' )
#define rep( i , x ) for ( int i = 0 ; i ++ < x ; )
 
const int maxn = 251000 ;
const int maxv = maxn << 1 ;
 
struct node {
        int ch[ 26 ] , parent , len ;
        node(  ) {
               memset( ch , 0 , sizeof( ch ) ) ;
               parent = len = 0 ; 
        }
} sam[ maxv ] ;
 
int root = maxv - 1 , V = 0 , last = maxv - 1 ; 
 
void add( int ch , int l ) {
        int p = last , np = ++ V ; 
        L( np ) = l ;
        for ( ; ! C( p , ch ) && p ; p = P( p ) ) C( p , ch ) = np ;
        if ( ! p ) P( np ) = root ; else {
               int q = C( p , ch ) ;
               if ( L( q ) == L( p ) + 1 ) P( np ) = q ; else {
                       int r = ++ V ;
                       N( r ) = N( q ) ;
                       L( r ) = L( p ) + 1 ; 
                       P( np ) = P( q ) = r ; 
                       for ( ; p && C( p , ch ) == q ; p = P( p ) ) C( p , ch ) = r ; 
               }
        }
        last = np ;
}
 
int s[ maxn ] , slen ;
 
void getstr(  ) {
        slen = 0 ; 
        int ch ; for ( ch = getchar(  ) ; ! check( ch ) ; ch = getchar(  ) ) ; 
        s[ ++ slen ] = ch - 'a' ;
        for ( ch = getchar(  ) ; check( ch ) ; ch = getchar(  ) ) {
               s[ ++ slen ] = ch - 'a' ;
        }
}
 
int main(  ) {
        getstr(  ) ;
        rep( i , slen ) add( s[ i ] , i ) ;
        int mlen = 0 , ans = 0 , t = root ;
        getstr(  ) ;
        rep( i , slen ) {
               int ch = s[ i ] ;
               if ( C( t , ch ) ) ++ mlen , t = C( t , ch ) ; else {
                       for ( ; t && ! C( t , ch ) ; t = P( t ) ) ;
                       if ( ! t ) t = root , mlen = 0 ; else {
                               mlen = L( t ) + 1 ;
                               t = C( t , ch ) ;
                       }
               }
               ans = max( ans , mlen ) ;
        }
        printf( "%d\n" , ans ) ;
        return 0 ; 
}

1812:

#include <cstdio>

#include <algorithm>

#include <cstring>

 

using namespace std ;

 

#define P( t ) sam[ t ].parent

#define C( t , x ) sam[ t ].child[ x ]

#define N( t ) sam[ t ]

#define F( t ) sam[ t ].fun

#define L( t ) sam[ t ].maxlen

 

const int maxn = 100100 ;

const int maxv = maxn << 1 ; 

 

struct node {

        int child[ 26 ] , parent , fun , maxlen ;

        node(  ) {

               memset( child , 0 , sizeof( child ) ) ;

               parent = fun = maxlen = 0 ; 

        }

} sam[ maxv ] ;

 

int last = maxv - 1 , root = maxv - 1 , V = 0 ; 

 

void extend( int ch ) {

        int np = ++ V , p = last ; 

        L( np ) = L( p ) + 1 ; 

        for ( ; p && ! C( p , ch ) ; p = P( p ) ) C( p , ch ) = np ; 

        if ( ! p ) P( np ) = root ; else {

               int q = C( p , ch ) ;

               if ( L( q ) == L( p ) + 1 ) P( np ) = q ; else {

                       int r = ++ V ;

                       N( r ) = N( q ) ; 

                       L( r ) = L( p ) + 1 ;

                       P( np ) = P( q ) = r ; 

                       for ( ; p && C( p , ch ) == q ; p = P( p ) ) C( p , ch ) = r ; 

               }

        }

        last = np ;

}

 

char s[ maxn ] ;

int dp[ maxv ] , len ;

 

void update( int &x , int val ) {

        x = max( x , val ) ;

}

 

int main(  ) {

        scanf( "%s" , s + 1 ) ;

        len = strlen( s + 1 ) ;

        for ( int i = 0 ; i ++ < len ; ) extend( s[ i ] - 'a' ) ;

        for ( int i = 0 ; i <= V ; ++ i ) dp[ i ] = L( i ) ;

        while ( scanf( "%s" , s + 1 ) != EOF ) {

               len = strlen( s + 1 ) ;

               for ( int i = 0 ; i <= V ; ++ i ) F( i ) = 0 ; 

               for ( int i = 1 , temp = 0 , t = root ; i <= len ; ++ i ) {

                       int ch = s[ i ] - 'a' ;

                       if ( C( t , ch ) ) update( F( t = C( t , ch ) ) , ++ temp ) ; else {

                               for ( ; t && ! C( t , ch ) ; t = P( t ) ) ;

                               if ( ! t ) t = root , temp = 0 ; else {

                                      temp = L( t ) + 1 ; 

                                      update( F( t = C( t , ch ) ) , temp ) ;

                               }

                       }

               }

               for ( int i = V ; i ; -- i ) update( F( P( i ) ) , F( i ) ) ;

               for ( int i = 0 ; i <= V ; ++ i ) dp[ i ] = min( dp[ i ] , F( i ) ) ;

        }

        int ans = 0 ; 

        for ( int i = 0 ; i <= V ; ++ i ) update( ans , dp[ i ] ) ;

        printf( "%d\n" , ans ) ;

        return 0 ; 

}
    原文作者:AmadeusChan
    原文地址: https://www.jianshu.com/p/c64be6d10e2e
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞