uva 719 - Glass Beads(后缀自动机)

uva 719 - Glass Beads(后缀自动机)

题意:求循环同构的最小表示的起点。

解题思路:这题用后缀自动机来解,牛刀杀鸡啊,我只是写写模板。。构造好sam之后,按字典序,dfs遍历,当深度达到n时,就返回当前节点的val值(也就是它的len),记录为k,那么答案就是k-n+1。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std ;

const int maxn = 1111111 ;
struct Suf_auto {
    int tot , last , c[26][maxn<<1] , pre[maxn<<1] , val[maxn<<1] ;
    inline void new_node ( int step ) {
        int i ;
        val[++tot] = step ;
        for ( i = 0 ; i < 26 ; i ++ ) c[i][tot] = 0 ;
        pre[tot] = 0 ;
    }
    void build ( char *s , int len ) {
        int i , j , k ;
        tot = 0 ;
		new_node ( 0 ) ;
		last = 1 ;
        for ( i = 0 ; i < len ; i ++ ) {
            new_node ( val[last] + 1 ) ;
            int np = tot ;
            k = s[i] - 'a' ;
            while ( !c[k][last] && last ) c[k][last] = tot , last = pre[last] ;
            if ( !last ) pre[tot] = 1 ;
            else {
                int q = c[k][last] ;
                if ( val[q] != val[last] + 1 ) {
                    new_node ( val[last] + 1 ) ;
                    for ( j = 0 ; j < 26 ; j ++ ) c[j][tot] = c[j][q] ;
                    pre[tot] = pre[q] ;
                    pre[q] = pre[np] = tot ;
                    while ( c[k][last] == q && last ) 
						c[k][last] = tot , last = pre[last] ;
                }
                else pre[tot] = q ;
            }
            last = np ;
        }
    }
	int dfs ( int rt , int step , int n ) {
		if ( step == n ) return val[rt] ;
		int i ;
		for ( i = 0 ; i < 26 ; i ++ )
			if ( c[i][rt] ) {
				int k = dfs ( c[i][rt] , step + 1 , n ) ;
				if ( k ) return k ;
			}
		return 0 ;
	}
	void solve ( int n ) {
		int i , j , k ;
		printf ( "%d\n" , dfs ( 1 , 0 , n ) - n + 1 ) ;
	}
	void travel ( int rt ) {
		int i ;
		printf ( "val[%d] = %d\n" , rt , val[rt] ) ;
		for ( i = 0 ; i < 26 ; i ++ )
			if ( c[i][rt] ) travel ( c[i][rt] ) ;
	}
} suf;

char s[111111] ;
int main () {
    int cas , len , i , j ;
    scanf ( "%d" , &cas ) ;
    while ( cas -- ) {
        scanf ( "%s" , s ) ;
		len = strlen ( s ) ;
		int n = len ;
		for ( i = 0 ; i < n ; i ++ ) s[len++] = s[i] ;
		s[len] = 0 ;
		suf.build ( s , len ) ;
	//	suf.travel ( 1 ) ;
		suf.solve ( n ) ;
    }
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值