zoukankan      html  css  js  c++  java
  • [TJOI2015]弦论

    题目

            点这里看题目。

    分析

            补习知识:
            既然可以求出原串中不同的子串的个数,那么我们同样可以求出含重复子串的个数,同样是(dp)
            (g(u)):从(u)节点出发含重复的子串的数量。
            转移:

    [g(u)=|end-pos(u)|+sum_{(u,v)in DAWG} g(v) ]

            因为可以重复,所以对于一个子串,它的出现次数就是它的结尾的(end-pos)的大小。
            正解部分,对于(t=0)的情况,就是一个模板题。对于(t=1)的情况,套用(t=0)的方法,这个时候我们改用(g)来确定该走哪一步。

    代码

    #include <cstdio>
    #include <cstring>
    
    const int MAXN = 5e5 + 5;
    
    template<typename _T>
    void read( _T &x )
    {
    	x = 0; char s = getchar();int f = 1;
    	while( s < '0' || '9' < s ) { f = 1; if( s == '-' ) f = -1; s = getchar(); }
    	while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + s - '0', s = getchar(); }
    	x *= f;
    }
    
    template<typename _T>
    void write( _T x )
    {
    	if( x < 0 ) { putchar( '-' ), x = -x; }
    	if( 9 < x ) { write( x / 10 ); }
    	putchar( x % 10 + '0' );
    }
    
    struct edge
    {
    	int to, nxt;
    }Graph[MAXN << 1];
    
    int f[MAXN << 1], g[MAXN << 1];
    int cnt[MAXN];
    int ep[MAXN << 1], seq[MAXN << 1], head[MAXN << 1];
    int ch[MAXN << 1][26], fa[MAXN << 1], mx[MAXN << 1];
    char A[MAXN];
    int N, T, K, rt, lst, tot, ecnt;
    
    void addEdge( const int from, const int to )
    {
    	ecnt ++;
    	Graph[ecnt].to = to, Graph[ecnt].nxt = head[from];
    	head[from] = ecnt;
    }
    
    void copy( const int a, const int b ) { fa[a] = fa[b], mx[a] = mx[b], memcpy( ch[a], ch[b], sizeof ch[b] ); }
    void expand( const char c )
    {
    	int x = c - 'a', p = lst, cur = ++ tot; 
    	mx[cur] = mx[p] + 1, lst = cur, ep[cur] = 1;
    	while( p && ! ch[p][x] ) ch[p][x] = cur, p = fa[p];
    	if( ! p ) { fa[cur] = rt; return ; }
    	int q = ch[p][x];
    	if( mx[q] == mx[p] + 1 ) { fa[cur] = q; return ; }
    	int nq = ++ tot; copy( nq, q );
    	mx[nq] = mx[p] + 1, fa[cur] = fa[q] = nq;
    	while( p && ch[p][x] == q ) ch[p][x] = nq, p = fa[p];
    }
    
    void topo()
    {
    	for( int i = 1 ; i <= tot ; i ++ ) cnt[mx[i]] ++;
    	for( int i = 1 ; i <= N ; i ++ ) cnt[i] += cnt[i - 1];
    	for( int i = tot ; i ; i -- ) seq[cnt[mx[i]] --] = i;
    }
    
    void DFS( const int u )
    {
    	for( int i = head[u], v ; i ; i = Graph[i].nxt )
    		DFS( v = Graph[i].to ), ep[u] += ep[v];
    }
    
    int main()
    {
    	scanf( "%s", A + 1 ); N = strlen( A + 1 );
    	read( T ), read( K );
    	rt = lst = ++ tot;
    	for( int i = 1 ; i <= N ; i ++ ) 
    		expand( A[i] );
    	for( int i = 2 ; i <= tot ; i ++ ) addEdge( fa[i], i );
    	DFS( 1 ), topo();
    	for( int i = tot, u ; i ; i -- )
    	{
    		if( ( u = seq[i] ) > 1 ) { f[u] = 1, g[u] = ep[u]; }
    		for( int j = 0 ; j < 26 ; j ++ )
    			if( ch[u][j] ) f[u] += f[ch[u][j]], g[u] += g[ch[u][j]];
    	}
    	if( K > f[1] ) { write( -1 ); return 0; }
    	if( T )
    	{
    		int p = rt, v;
    		while( true )
    		{
    			for( int i = 0 ; i < 26 ; i ++ )
    			{
    				v = ch[p][i];
    				if( K <= ep[v] ) { putchar( 'a' + i ), putchar( '
    ' ); return 0; }
    				else if( K <= g[v] ) { putchar( 'a' + i ), K -= ep[v], p = ch[p][i]; break; }
    				K -= g[v];
    			}
    		}
    		putchar( '
    ' );
    	}
    	else
    	{
    		int p = rt, v;
    		while( K )
    		{
    			for( int i = 0 ; i < 26 ; i ++ )
    			{
    				v = ch[p][i];
    				if( f[v] >= K ) { p = ch[p][i], putchar( 'a' + i ), K --; break; }
    				K -= f[v];
    			}
    		}
    		putchar( '
    ' );
    	}
    	return 0;
    }
    
  • 相关阅读:
    456. 132 Pattern
    496. Next Greater Element I
    503. Next Greater Element II
    341. Flatten Nested List Iterator
    232. Implement Queue using Stacks
    225. Implement Stack using Queues
    208. Implement Trie (Prefix Tree)
    思考--为何早晨型人更容易成功
    Listary的使用
    【运维】虚拟机如何安装CentOS
  • 原文地址:https://www.cnblogs.com/crashed/p/12898694.html
Copyright © 2011-2022 走看看