POJ 3576
题目链接:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=16065
题意:
问怎样按照题目的规则得到最少的点(题意实在是无法描述)
思路:
首先知道Trie树能形成这些单词的字典树。然后就看树上有多少个子树可以合并。
所以问题转换成如何确定以某个点为根节点的子树的Hash值。
本题采用unsigned long long表示Hash值,如果溢出自动剔除高位。然而开脑洞测几种Hash方法,换一下常量就行了。
源码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
#define ULL unsigned long long
#define LL long long
#define SEED 11198411
const int MAXN = 150000;
const int MAXM = 26;
struct Trie
{
int son[MAXN][MAXM];
int cnt, en[MAXN];
int root;
char cun[MAXN];
void init(){
root = 0;
cnt = 1;
memset(en, 0, sizeof(en));
memset(son, -1, sizeof(son));
}
void ins(char *str, int val)
{
// printf("str = %s\n", str);
int pos = root;
for(int i = 0 ; str[i] != '\0' ; i++){
int mark = str[i] - 'a';
// printf("mark = %d\n", mark);
if(son[pos][mark] == -1){
cun[cnt] = str[i];
son[pos][mark] = cnt++;
}
pos = son[pos][mark];
if(str[i + 1] == '\0')
en[pos] = val;
}
// printf("\n");
}
}tree;
struct Edge
{
int deep;
int en;
ULL hash;
}e[MAXN];
int deep[MAXN];
void dfs(int u)
{
e[u].deep = 0;
e[u].hash = 1;
e[u].en = tree.en[u];
LL t = 1;
for(int i = 0 ; i < 26 ; i++){
if(tree.son[u][i] != -1){
dfs(tree.son[u][i]);
e[u].deep = max(e[u].deep, e[tree.son[u][i]].deep);
e[u].hash = e[u].hash + (e[tree.son[u][i]].hash) * t + tree.cun[tree.son[u][i]] - 'a' + tree.en[tree.son[u][i]];
}
t *= 23;
}
e[u].deep++;
// printf("u = %d, deep = %d, hash = %I64u, en = %d, cun = %c\n", u, e[u].deep, e[u].hash, e[u].en, tree.cun[u]);
}
char str[35];
bool cmp(Edge u, Edge v)
{
if(u.deep != v.deep) return u.deep < v.deep;
if(u.hash != v.hash) return u.hash < v.hash;
if(u.en != v.en) return u.en < v.en;
}
int main()
{
// freopen("POJ 3576.in", "r", stdin);
int n;
while(scanf("%d", &n) != EOF){
tree.init();
for(int i = 0 ; i < n ; i++){
scanf("%s", str);
tree.ins(str, 1);
}
dfs(0);
sort(e, e + tree.cnt, cmp);
// printf("tree.cnt = %d\n", tree.cnt);
int ans = 0;
for(int i = 1 ; i < tree.cnt ; i++){
if(e[i].hash != e[i - 1].hash || e[i].deep != e[i-1].deep || e[i].en != e[i-1].en)
ans++;
}
printf("%d\n", ans + 1);
}
return 0;
}