传送门:【HDU】4117 GRE Words
题目分析:水不了啊狸的打字机就来水这题了= =。。。
首先建立ac自动机,然后用fail指针的反向关系建边,构造fail指针树。fail指针树中每个结点u表示的串都是其子节点v的后缀(同时该后缀是所有串中最长的)。对fail指针树dfs一次得到时间戳,当要求以串i结尾的最大价值,首先我们需要知道以串i的子串j结尾的最大价值val。因为在树中我们有关系如上所述,所以我们可以对i串的每个字符xi(对应树上一个结点)找到其在树上的价值最大的后缀,然后取最大加上串i本身的价值,即要求的val。然后我们对i的子树【in[i] , ou[i]】更新,即用val更新区间【in[i] , ou[i]】。查询的时候便是单点查询,查询in[xi](xi为属于串i的每个字符)上的最大值。
我语文体育老师教的。
代码如下:
#include <set> #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; #pragma comment(linker, "/STACK:16777216") #define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define clr( a , x ) memset ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define root 1 , 1 , ac.cur #define mid ( ( l + r ) >> 1 ) const int MAXN = 300005 ; const int MAXE = 1000005 ; const int INF = 0x3f3f3f3f ; struct ac_automaton { int next[MAXN][26] ; int fail[MAXN] ; int ac_root ; int cur ; int Q[MAXN] , head , tail ; int newnode () { rep ( i , 0 , 26 ) next[cur][i] = -1 ; return cur ++ ; } void clear () { cur = 0 ; ac_root = newnode () ; } inline int encode ( char c ) { return c - 'a' ; } void insert ( char* , int ) ; void build () { head = tail = 0 ; fail[ac_root] = ac_root ; rep ( i , 0 , 26 ) { if ( ~next[ac_root][i] ) { fail[next[ac_root][i]] = ac_root ; Q[tail ++] = next[ac_root][i] ; } else next[ac_root][i] = ac_root ; } while ( head != tail ) { int now = Q[head ++] ; rep ( i , 0 , 26 ) { if ( ~next[now][i] ) { fail[next[now][i]] = next[fail[now]][i] ; Q[tail ++] = next[now][i] ; } else next[now][i] = next[fail[now]][i] ; } } } } ; struct Edge { int v , n ; Edge () {} Edge ( int v , int n ) : v ( v ) , n ( n ) {} } ; ac_automaton ac ; Edge E[MAXE] ; int lazy[MAXN << 2] ; int maxv[MAXN << 2] ; int H[MAXN] , cntE ; int N[MAXN] , cntN ; int d[MAXN] ; int word[MAXN] ; int val[MAXN] ; int in[MAXN] , ou[MAXN] , dfs_clock ; char buf[MAXN] ; int n ; void clear () { cntE = 0 ; dfs_clock = 0 ; clr ( N , -1 ) ; clr ( H , -1 ) ; clr ( lazy , 0 ) ; clr ( maxv , 0 ) ; } void addedge ( int u , int v , int H[] ) { E[cntE] = Edge ( v , H[u] ) ; H[u] = cntE ++ ; } void ac_automaton :: insert ( char buf[] , int idx ) { int now = ac_root ; for ( int i = 0 ; buf[i] ; ++ i ) { int index = encode ( buf[i] ) ; if ( next[now][index] == -1 ) next[now][index] = newnode () ; now = next[now][index] ; addedge ( idx , now , N ) ; } word[idx] = now ; } void dfs ( int u ) { in[u] = ++ dfs_clock ; for ( int i = H[u] ; ~i ; i = E[i].n ) dfs ( E[i].v ) ; ou[u] = dfs_clock ; } void push_down ( int o ) { if ( lazy[o] ) { lazy[ls] = max ( lazy[ls] , lazy[o] ) ; lazy[rs] = max ( lazy[rs] , lazy[o] ) ; maxv[ls] = max ( maxv[ls] , lazy[o] ) ; maxv[rs] = max ( maxv[rs] , lazy[o] ) ; lazy[o] = 0 ; } } void push_up ( int o ) { maxv[o] = max ( maxv[ls] , maxv[rs] ) ; } void update ( int L , int R , int v , int o , int l , int r ) { if ( l == r ) { lazy[o] = max ( lazy[o] , v ) ; maxv[o] = max ( maxv[o] , v ) ; return ; } push_down ( o ) ; int m = mid ; if ( L <= m ) update ( L , R , v , lson ) ; if ( m < R ) update ( L , R , v , rson ) ; push_up ( o ) ; } int query ( int x , int o , int l , int r ) { if ( l == r ) return maxv[o] ; push_down ( o ) ; int m = mid ; if ( x <= m ) return query ( x , lson ) ; else return query ( x , rson ) ; } void solve () { int x ; clear () ; ac.clear () ; scanf ( "%d" , &n ) ; For ( i , 1 , n ) { scanf ( "%s%d" , buf , &val[i] ) ; ac.insert ( buf , i ) ; } ac.build () ; rep ( i , 1 , ac.cur ) addedge ( ac.fail[i] , i , H ) ; dfs ( ac.ac_root ) ; int ans = 0 ; For ( u , 1 , n ) { if ( val[u] < 0 ) continue ; int tmp = 0 ; for ( int i = N[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; tmp = max ( tmp , query ( in[v] , root ) ) ; } ans = max ( tmp + val[u] , ans ) ; update ( in[word[u]] , ou[word[u]] , tmp + val[u] , root ) ; } printf ( "%d\n" , ans ) ; } int main () { int T , cas = 0 ; scanf ( "%d" , &T ) ; while ( T -- ) { printf ( "Case #%d: " , ++ cas ) ; solve () ; } return 0 ; }