码迷,mamicode.com
首页 > 其他好文 > 详细

UVA11732 【"strcmp()" Anyone?】

时间:2021-06-19 18:47:32      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:需要   结束   print   clu   while   公共前缀   hack   int   bit   

如果按照题意模拟的话是肯定会超时的(题目都好心告诉你了),考虑优化。

我们发现对于两个串我们只用求它们的最长公共前缀即可。

如果将所有串建一棵\(trie\),那最长公共前缀就对应到它们的结束节点在\(trie\)树上的\(lca\)。所以我们建好\(trie\)后只用遍历一遍所有节点看看它是几个串的\(lca\)即可。

其实只需要一波数学推导即可。

对于一条边\(u->v\),我们统计出子树\(u\)\(v\)分别有多少结束标记\(sum\),然后对应以\(u\)为lca的串就增加\(sum[v] \times (sum[u] - sum[v])\)

然后我们发现这是成对出现的所以要除以\(2\)

最后加上上述值乘上根到当前节点的距离乘\(2\)\(1\)即可。

如果当前节点是多个串的结尾,那还要考虑这些串互相的贡献。其实也很好考虑。

\(End[x]\)代表节点\(x\)有多少串在这结尾,则答案会加上\((End[x] \times (End[x] - 1) / 2) * ((dis + 1) \times 2)\)

但是写完之后交上去发现错了。

可参考hack数据:

2

app

apple

原因是直接\(sum[v] \times (sum[u] - sum[v])\)并不是所有乘 \(2\),与结尾刚好到\(x\)的串其实就只有一次,所以要再额外考虑。

Code:

#include <bits/stdc++.h>
using namespace std;
int trie[4000010][62], tot = 1;
char s[1010];
long long End[4000010], sum[4000010];
int n;
long long ans;
int num;
int f(char ch) {
	if (isdigit(ch)) {
		return ch - ‘0‘;
	}
	if (‘a‘ <= ch && ch <= ‘z‘) {
		return ch - ‘a‘ + 10;
	}
	return ch - ‘A‘ + 36;
}
void dfs(int x, int dis) {
	long long cnt = 0;
	for (int i = 0; i < 62; i++) {
		if (trie[x][i]) {
			cnt += sum[trie[x][i]] * (sum[x] - sum[trie[x][i]] - End[x]);
			cnt += End[x] * sum[trie[x][i]] * 2;
			dfs(trie[x][i], dis + 1);
			trie[x][i] = 0;
		}
	}
	cnt >>= 1;
	ans += cnt * ((dis << 1) + 1);
	ans += (End[x] * (End[x] - 1) >> 1) * ((dis + 1) << 1);
	End[x] = 0;
	sum[x] = 0;
}
int main() {
	while (scanf("%d", &n) != EOF && n) {
		num++;
		tot = 1;
		for (int i = 1, len, p; i <= n; i++) {
			scanf("%s", s + 1);
			len = strlen(s + 1);
			p = 1;
			for (int j = 1; j <= len; j++) {
				sum[p]++;
				if (!trie[p][f(s[j])]) trie[p][f(s[j])] = ++tot;
				p = trie[p][f(s[j])];
			}
			sum[p]++;
			End[p]++;
		}
		ans = 0;
		dfs(1, 0);
		printf("Case %d: %lld\n", num, ans);
	}
	return 0;
}

UVA11732 【"strcmp()" Anyone?】

标签:需要   结束   print   clu   while   公共前缀   hack   int   bit   

原文地址:https://www.cnblogs.com/zcr-blog/p/14901180.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!