题目链接:【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 ;
}