URAL 1517 Freedom of Choice

题目大意:

        只有一个测例,测例中给出字符串长度N(1 ≤ N ≤ 100,000),接下来给出两个长度为N的字符串(都由大写字母组成),要求输出最长公共连续子序列。

题目链接

注释代码:

/*         
 * Problem ID : URAL 1517 Freedom of Choice
 * Author     : Lirx.t.Una         
 * Language   : Visual C 2010      
 * Run Time   : 0.171         
 * Run Memory : 4232KB         
*/

#pragma GCC optimize("O2")

#include <stdio.h>

#define	CHN			'Z'
#define	MAXN		200002

#define	MAX(x,y)	( (x) > (y) ? (x) : (y) )
#define	MIN(x,y)	( (x) < (y) ? (x) : (y) )

int		buf1[MAXN];
int		buf2[MAXN];
int		buf3[MAXN];

int		sa[MAXN];
int		h[MAXN];
int	*	rk;

char	s[MAXN];

int
keq( int *v, int x, int y, int l ) {

	return v[x] == v[y] && v[x + l] == v[y + l];
}

void
bd_sa( char *s, int n, int mv ) {

	int *	vi;
	int	*	sv;
	int	*	lv;
	int	*	t;

	int		v;
	int		cl;

	int		i, j;

	vi = buf1;
	sv = buf2;
	lv = buf3;

	for ( i = 0; i <= mv; i++ )	sv[i] = 0;
	for ( i = 0; i <= n; i++ ) sv[ vi[i] = s[i] ]++;
	for ( i = 1; i <= mv; i++ ) sv[i] += sv[i - 1];
	for ( i = n; i >= 0; i-- ) sa[ --sv[ vi[i] ] ] = i;

	for ( cl = 1, v = 0; v <= n; cl <<= 1, mv = v ) {
	
		for ( j = 0, i = n - cl + 1; i <= n; i++ ) lv[j++] = i;
		for ( i = 0; i <= n; i++ ) if ( sa[i] >= cl ) lv[j++] = sa[i] - cl;
		
		for ( i = 0; i <= mv; i++ ) sv[i] = 0;
		for ( i = 0; i <= n; i++ ) sv[ vi[ lv[i] ] ]++;
		for ( i = 1; i <= mv; i++ ) sv[i] += sv[i - 1];
		for ( i = n; i >= 0; i-- ) sa[ --sv[ vi[ lv[i] ] ] ] = lv[i];

		for ( t = vi, vi = lv, lv = t, vi[ sa[0] ] = 0, v = 1, i = 1; i <= n; i++ )
			vi[ sa[i] ] = keq( lv, sa[i - 1], sa[i], cl ) ? v - 1 : v++;
	}

	rk = vi;
}

void
bd_h( char *s, int n ) {

	int		i, j;
	int		cl;

	for ( cl = 0, i = 0; i < n; h[ rk[i++] ] = cl )
		for ( cl ? --cl : 0, j = sa[ rk[i] - 1 ]; s[i + cl] == s[j + cl]; cl++ );
}

int
main() {

	int		len;//字符串长
	int		n;//合并后的长度
	int		ml;//maximum length,最长公共子串长度
	int		ll;//lft link,左链接临时变量
	int		lft, rht;//最长公共子串的左右区间

	int		i;

	scanf("%d", &len);
	scanf("%s", s);
	s[len] = '#';
	scanf("%s", s + len + 1);
	n = ( len << 1 ) + 1;

	bd_sa( s, n, CHN );
	bd_h( s, n );

	for ( ml = 0, i = 1; i <= n; i++ )
		if ( h[i] > ml )
			if ( ( ll = MIN( sa[i - 1], sa[i] ) ) < len && MAX( sa[i - 1], sa[i] ) > len ) {
			
				ml  = h[i];
				lft = ll;//更新左边界
				rht = lft + ml;//更新右边界
			}

	//直接输出,不要逐个输出
	s[rht] = '\0';
	puts(s + lft);
	
	return 0;
}

无注释代码:

#pragma GCC optimize("O2")

#include <stdio.h>

#define	CHN			'Z'
#define	MAXN		200002

#define	MAX(x,y)	( (x) > (y) ? (x) : (y) )
#define	MIN(x,y)	( (x) < (y) ? (x) : (y) )

int		buf1[MAXN];
int		buf2[MAXN];
int		buf3[MAXN];

int		sa[MAXN];
int		h[MAXN];
int	*	rk;

char	s[MAXN];

int
keq( int *v, int x, int y, int l ) {

	return v[x] == v[y] && v[x + l] == v[y + l];
}

void
bd_sa( char *s, int n, int mv ) {

	int *	vi;
	int	*	sv;
	int	*	lv;
	int	*	t;

	int		v;
	int		cl;

	int		i, j;

	vi = buf1;
	sv = buf2;
	lv = buf3;

	for ( i = 0; i <= mv; i++ )	sv[i] = 0;
	for ( i = 0; i <= n; i++ ) sv[ vi[i] = s[i] ]++;
	for ( i = 1; i <= mv; i++ ) sv[i] += sv[i - 1];
	for ( i = n; i >= 0; i-- ) sa[ --sv[ vi[i] ] ] = i;

	for ( cl = 1, v = 0; v <= n; cl <<= 1, mv = v ) {
	
		for ( j = 0, i = n - cl + 1; i <= n; i++ ) lv[j++] = i;
		for ( i = 0; i <= n; i++ ) if ( sa[i] >= cl ) lv[j++] = sa[i] - cl;
		
		for ( i = 0; i <= mv; i++ ) sv[i] = 0;
		for ( i = 0; i <= n; i++ ) sv[ vi[ lv[i] ] ]++;
		for ( i = 1; i <= mv; i++ ) sv[i] += sv[i - 1];
		for ( i = n; i >= 0; i-- ) sa[ --sv[ vi[ lv[i] ] ] ] = lv[i];

		for ( t = vi, vi = lv, lv = t, vi[ sa[0] ] = 0, v = 1, i = 1; i <= n; i++ )
			vi[ sa[i] ] = keq( lv, sa[i - 1], sa[i], cl ) ? v - 1 : v++;
	}

	rk = vi;
}

void
bd_h( char *s, int n ) {

	int		i, j;
	int		cl;

	for ( cl = 0, i = 0; i < n; h[ rk[i++] ] = cl )
		for ( cl ? --cl : 0, j = sa[ rk[i] - 1 ]; s[i + cl] == s[j + cl]; cl++ );
}

int
main() {

	int		len;
	int		n;
	int		ml;
	int		ll;
	int		lft, rht;

	int		i;

	scanf("%d", &len);
	scanf("%s", s);
	s[len] = '#';
	scanf("%s", s + len + 1);
	n = ( len << 1 ) + 1;

	bd_sa( s, n, CHN );
	bd_h( s, n );

	for ( ml = 0, i = 1; i <= n; i++ )
		if ( h[i] > ml )
			if ( ( ll = MIN( sa[i - 1], sa[i] ) ) < len && MAX( sa[i - 1], sa[i] ) > len ) {
			
				ml  = h[i];
				lft = ll;
				rht = lft + ml;
			}

	s[rht] = '\0';
	puts(s + lft);
	
	return 0;
}

单词解释:

Albania:阿尔巴尼亚,东欧国家

Albanian:阿尔巴尼亚人

bear with:vt, 忍受,宽容

democratic:adj, 民主的

presidential:adj, 总统的,首长的

politician:n, 政治家,政客

liberal:n, 自由主义者; adj, 自由主义的

conservative:n, 保守派; adj, 保守的

rival:n, 对手,竞争者

intention:n, 意图,目的

post:n, 岗位

compete:vt, 竞争,比赛

entertain:vt, 娱乐,款待

dirt:n, 污泥,污垢

cheer:n, 欢呼,愉快

approval:n, 认可,赞成,批准

occasion:n, 时机,场合

devote to:vt, 致力于,专注于

voter:n, 投票人

blame sb for sth:责备某人某事

opponent:n, 对手,反对派

corruption:n, 贪污,腐败

disrespect:n, 失礼,不敬

elder:n, 老人,长辈

terrorism:n, 恐怖主义

affiliation:n, 友好关系,联盟

socialist:n, 社会主义者; adj, 社会主义的

comrade:n, 同志(共产党的正式叫法)

fragment:n, 碎片,片段

identical:adj, 完全相同的



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值