[BZOJ1174][Balkan2007]Toponyms

[BZOJ1174][Balkan2007]Toponyms

试题描述

给你一个字符集合,你从其中找出一些字符串出来. 希望你找出来的这些字符串的最长公共前缀*字符串的总个数最大化.

输入

第一行给出数字N.N在[2,1000000] 下面N行描述这些字符串,长度不超过20000 。保证输入文件不超过10MB

输出

a single line with an integer representing the maximal level of complexity Lc(T).

输入示例

7
Jora de Sus
Orhei
Jora de Mijloc
Joreni
Jora de Jos
Japca
Orheiul Vechi

输出示例

24

数据规模及约定

你可以认为字符总数不超过 500W。。。

题解

本来是到挺裸的题,记一下 trie 树上每个节点为根的子树中包含的单词个数,乘一下深度再取一下 max 就是答案了。

这题却非得卡空间。。。

用邻接表存 trie 树的边;还有读入别再另开一个字符串了,直接 getchar()。。。

窝居然卡过去了 233。。。。。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <vector>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
	return x * f;
}

#define maxn 5000010
#define LL long long

int n, rt, ToT, m, val[maxn], head[maxn], nxt[maxn], to[maxn];
char ec[maxn];

LL ans;
void insert() {
	int u = rt;
	val[u]++;
	char C = getchar();
	for(int i = 0; C != '
'; i++, C = getchar()) {
		int v = -1;
		for(int e = head[u]; e; e = nxt[e])
			if(ec[e] == C){ v = to[e]; break; }
		if(v < 0) to[++m] = ++ToT, ec[m] = C, nxt[m] = head[u], head[u] = m, v = ToT;
		val[u = v]++;
		ans = max(ans, (LL)val[u] * (i + 1));
	}
	return ;
}

int main() {
	n = read(); rt = ToT = 1;
	for(int i = 1; i <= n; i++) insert();
	
	printf("%lld
", ans);
	
	return 0;
}
原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6484348.html