【UVALive】7502 Suffixes and Palindromes【根据sa数组以及回文半径数组构造字典序最小的串】

来源:互联网 发布:淘宝男士外贸原单店铺 编辑:程序博客网 时间:2024/06/06 08:29

题目链接:【UVALive】7502 Suffixes and Palindromes

根据回文半径数组能得出一堆不等相等关系,相等缩点,不等建边。
根据sa数组的对偶数组rank数组的性质,考虑sa[i]和sa[i-1],如果如果rank[sa[i]+1]>rank[sa[i-1]+1]则s[sa[i]]可以等于s[sa[i-1]];如果rank[sa[i]+1]>rank[sa[i-1]+1]则s[sa[i]]必须大于s[sa[i-1]]。
根据以上信息可以得出字典序最小的串。

#include <bits/stdc++.h>using namespace std ;const int MAXN = 200005 ;const int MAXE = 610005 ;struct Edge {    int v , n ;    Edge () {}    Edge ( int v , int n ) : v ( v ) , n ( n ) {}} ;Edge E[MAXE] ;int H[MAXN] , H2[MAXN] , cntE ;int f[MAXN] , R[MAXN] ;int sa[MAXN] , rnk[MAXN] ;int p[MAXN] ;char col[MAXN] ;int n , m ;void addedge ( int u , int v ) {    E[cntE] = Edge ( v , H[u] ) ;    H[u] = cntE ++ ;}void addedge2 ( int u , int v ) {    E[cntE] = Edge ( v , H2[u] ) ;    H2[u] = cntE ++ ;}int Wrong () {    return printf ( "Wrong calculation!\n" ) ;}int F ( int x ) {    return p[x] == x ? x : ( p[x] = F ( p[x] ) ) ;}int make_same ( int x , int y ) {    if ( x <= 0 || y >= m ) return 0 ;    if ( x % 2 != y % 2 ) return 0 ;    //printf ( "same %d %d\n" , x , y ) ;    p[F ( x )] = F ( y ) ;    return 1 ;}int make_diff ( int x , int y ) {    if ( x < 0 || y > m ) return 0 ;    if ( x == 0 || y == m ) return 1 ;    if ( x % 2 == 1 && y % 2 == 1 ) return 0 ;    if ( F ( x ) == F ( y ) ) return 0 ;    addedge ( x , y ) ;    //printf ( "diff %d %d\n" , x , y ) ;    return 1 ;}int solve () {    scanf ( "%d" , &n ) ;    for ( int i = 1 ; i <= n ; ++ i ) {        scanf ( "%d" , &sa[i] ) ;        rnk[++ sa[i]] = i ;    }    rnk[n + 1] = 0 ;    for ( int i = 2 ; i <= n * 2 ; ++ i ) {        scanf ( "%d" , &R[i] ) ;        ++ R[i] ;    }    m = ( n + 1 ) << 1 ;    R[1] = R[m - 1] = f[1] = 1 ;    cntE = 0 ;    for ( int i = 0 ; i < m ; ++ i ) {        p[i] = i ;        col[i] = 0 ;        H[i] = H2[i] = -1 ;    }    for ( int i = 2 , r = 0 , pos = 0 ; i < m ; ++ i ) {        for ( f[i] = r > i ? min ( r - i , f[pos * 2 - i] ) : 1 ; f[i] < R[i] ; ++ f[i] ) {            if ( !make_same ( i - f[i] , i + f[i] ) ) return Wrong () ;        }        if ( f[i] > R[i] ) return Wrong () ;        if ( !make_diff ( i - f[i] , i + f[i] ) ) return Wrong () ;        if ( i + f[i] > r ) r = i + f[i] , pos = i ;    }    for ( int i = 0 ; i < m ; ++ i ) F ( i ) ;    for ( int i = 0 ; i < m ; ++ i ) {        for ( int j = H[i] ; ~j ; j = E[j].n ) {            if ( p[i] == p[E[j].v] ) return Wrong () ;            addedge2 ( p[i] , p[E[j].v] ) ;            addedge2 ( p[E[j].v] , p[i] ) ;        }    }    int color = 'a' ;    col[p[sa[1] << 1]] = color ;    for ( int i = 2 ; i <= n ; ++ i ) {        int x = sa[i] << 1 , y = sa[i - 1] << 1 , cansame = 1 ;        if ( rnk[sa[i] + 1] < rnk[sa[i - 1] + 1] ) cansame = 0 ;        //printf ( "cansame = %d\n" , cansame ) ;        if ( col[p[x]] ) {            if ( cansame && col[p[x]] < col[p[y]] ) return Wrong () ;            else if ( !cansame && col[p[x]] <= col[p[y]] ) return Wrong () ;        } else {            for ( int j = H2[p[x]] ; ~j ; j = E[j].n ) if ( col[E[j].v] == color ) cansame = 0 ;            if ( !cansame ) ++ color ;            if ( color > 'z' ) return Wrong () ;            col[p[x]] = color ;        }    }    for ( int i = 1 ; i <= n ; ++ i ) printf ( "%c" , col[p[i << 1]] ) ;    puts ( "" ) ;}int main () {    int T ;    scanf ( "%d" , &T ) ;    for ( int i = 1 ; i <= T ; ++ i ) {        printf ( "Case #%d: " , i ) ;        solve () ;    }    return 0 ;}
0 0