Neerc2011 Dictionary Size

Neerc2011 Dictionary Size

Time Limit: 1 Sec Memory Limit: 64 MB
Submit: 155 Solved: 42
[ Submit][ Status]

Description

某国颁布了一本 n (n ≤ 10 000) 个单词的词典。单词长
度不超过 40。
该国的造词法是这样的:
1: 词典中的单词是一个词。
2: 能分为两部分的,其中前一部分是一个词典词或者其非
空前缀,后一部分是一个词典词或者其非空后缀的词。
求能造出的不相同的词汇数目。

Input

Output

Sample Input

3
abc
def
abef

Sample Output

60

HINT


这题没看题解前完全不会...

就是保证前缀最长,用两个trie,一个记录前缀,一个记录后缀

然后匹配就好了

注:输入一个a,答案是2,分别为a,aa

#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 11000;
struct Ttrie{
	struct node{
		node *ch[26];
		void clear(){ memset(ch, 0, sizeof(ch)); }
	}a[maxn * 40], *root;
	int tot;
	node *newnode(){ ++tot, a[tot].clear(); return &a[tot]; }
	void add(char s[], int sum[]){
		int len = strlen(s);
		node *p = root;
		for (int i = 0; i < len; i ++){
			if (!p->ch[s[i] - 'a']) p->ch[s[i] - 'a'] = newnode(), sum[s[i] - 'a'] ++;
			p = p->ch[s[i] - 'a'];
		}
	}
	void clear(){ tot = 0, root = newnode();}
	long long solve(int sum[], bool b[]){
		long long ans = 0;
		for (int i = 2; i <= tot; i ++){
			for (int j = 0; j < 26; j ++)
				if (!a[i].ch[j]) ans += sum[j];
				else if (b[j]) ans ++;
		}
		return ans;
	}
}trie;
char s[maxn][41];
int n, sum[41]; bool b[41], d[41];
long long ans;
void init(){
	trie.clear();
	memset(b, 0, sizeof(b));
	memset(sum, 0, sizeof(sum)); 
	ans = 0; memset(d, 0, sizeof(d));
	for (int i = 0; i < n; i ++){
		scanf("%s", s[i]); int len = strlen(s[i]);
		reverse(s[i], s[i] + len);
		b[s[i][0] - 'a'] = 1; trie.add(s[i], sum);
		reverse(s[i], s[i] + len);
		if (len == 1 && !d[s[i][0] - 'a'])
			d[s[i][0] - 'a'] = 1, ans ++;
	}
}
int asd[maxn];
void work(){
	trie.clear();
	for (int i = 0; i < n; i ++)
		trie.add(s[i], asd);
	ans += trie.solve(sum, b);
	cout <<ans <<endl;
}
int main(){
	while (scanf("%d", &n) != EOF) init(), work();
	return 0;
}


你可能感兴趣的:(trie)