zoukankan      html  css  js  c++  java
  • spoj 8222 Substrings (后缀自动机)

    spoj 8222 Substrings

    题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值。求F(1)..F(Length(S)) 

    解题思路:我们构造S的SAM,那么对于一个节点s,它的长度范围是[Min(s),Max(s)],同时他的出现次数是|Right(s)|。那么我们用|Right(s)|去更新F(Max(s))的值。那么现在的问题是如何快速求 |right(s)| 了还记得论文里parent tree吗?看看那个就知道了,不懂可以留言。接下来还有一步,我们现在只更新了节点代表串长度的f[l],那介于 s->len 和 s->fa->len的长度的那些串怎么办呢?好办,我们从长往短dp推下来就可以了,因为长的串出现了,短的必然出现了,比如长为4的出现了5次,那么长为3,2,1的必然至少出现5次,这样就把[s->len,s->fa->len]区间的也都更新进去了。(另外这题数据好弱。。我把字符范围误打成0->10都过了,侥幸排在了第一!!!)

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std ;
    
    const int maxn = 250005 ;
    
    int fa[maxn<<2] , c[26][maxn<<2] , val[maxn<<2] ;
    int last , tot ;
    int f[maxn] , g[maxn<<2] ;
    
    int max ( int a , int b ) { return a > b ? a : b ; }
    
    inline int new_node ( int step ) {
    	int i ;
    	val[++tot] = step ;
    	for ( i = 0 ; i < 26 ; i ++ ) c[i][tot] = 0 ;
    	fa[tot] = 0 ;
    	return tot ;
    }
    
    void add ( int k ) {
    	int p = last , i ;
    	int np = new_node ( val[p] + 1 ) ;
    	while ( p && !c[k][p] ) c[k][p] = np , p = fa[p] ;
    	if ( !p ) fa[np] = 1 ;
    	else {
    		int q = c[k][p] ;
    		if ( val[q] == val[p] + 1 ) fa[np] = q ;
    		else {
    			int nq = new_node ( val[p] + 1 ) ;
    			for ( i = 0 ; i < 26 ; i ++ ) c[i][nq] = c[i][q] ;
    			fa[nq] = fa[q] ;
    			fa[np] = fa[q] = nq ;
    			while ( p && c[k][p] == q ) c[k][p] = nq , p = fa[p] ;
    		}
    	}
    	last = np ;
    }
    
    void init () {
    	tot = 0 ;
    	last = new_node ( 0 ) ;
    }
    
    char s[maxn] ;
    int pos[maxn<<2] , ws[maxn<<2] ;
    int main () {
    	while ( scanf ( "%s" , s ) != EOF ) {
    		init () ;
    		int i , len = strlen ( s ) ;
    		for ( i = 0 ; i < len ; i ++ ) add ( s[i] - 'a' ) ;
    		for ( i = 1 ; i <= tot ; i ++ ) ws[i] = 0 ;
    		for ( i = 1 ; i <= tot ; i ++ ) ws[val[i]] ++ ;
    		for ( i = 1 ; i <= tot ; i ++ ) ws[i] += ws[i-1] ;
    		for ( i = 1 ; i <= tot ; i ++ ) pos[ws[val[i]]--] = i ;
    		for ( i = 1 ; i <= tot ; i ++ ) g[i] = 0 ;
    		for ( i = 1 ; i <= len ; i ++ ) f[i] = 0 ;
    		int p = 1 ;
    		for ( i = 0 ; i < len ; i ++ ) g[p=c[s[i]-'a'][p]] ++ ;
    		for ( i = tot ; i >= 1 ; i -- ) {
    			p = pos[i] ;
    			f[val[p]] = max ( f[val[p]] , g[p] ) ;
    			g[fa[p]] += g[p] ;
    		}
    		for ( i = len - 1 ; i >= 1 ; i -- )
    			f[i] = max ( f[i] , f[i+1] ) ;
    		for ( i = 1 ; i <= len ; i ++ )
    			printf ( "%d
    " , f[i] ) ;
    	}
    }


  • 相关阅读:
    05、镜像操作
    04、docker安装、启动服务
    03、docker架构的介绍
    02、docker前身LXC
    01、dcoker介绍
    08、Zabbix分布式配置
    07、Zabbix日常问题汇总
    06、1.9 Zabbix监控MYSQL主从
    05、zabbix邮件报警
    04、zabbix自动发现
  • 原文地址:https://www.cnblogs.com/pangblog/p/3329109.html
Copyright © 2011-2022 走看看