题解 P4305 【[JLOI2011]不重复数字】

Snowflake_Pink

2019-03-05 23:26:19

Solution

- 打个广告:[$Blog$](https://www.17shou.vip/) - 翻了所有的题解,发现竟然没有用$Trie$字典树做的,那我就来一发。 - $Trie$字典树的复杂度对于这道题来说还行,刚好卡的过去,我只是提供一种思路,泥萌最好还是用哈希表。 - 计算复杂度: - 数字长度$\leq 32$,数字总数$\leq 50000$,数据组数$\leq 50$ - 最坏所有数字都不一样,一组数据共建树结点次数:$32 \times 50000 = 1600000 = 1.6 \times 10^6$。 - $50$组数据:$1.6 \times 10^6 \times 50 = 8 \times 10^7$ - 所以说可以刚刚好卡过了。 - 算法: - 每读入一个数,就添加到字典树中,到最后一个结点发现不存在时,输出这个数;存在时,不输出这个数。以达到去重效果。 - Code: ```cpp #include <iostream> #include <cstdio> #include <cstring> using namespace std; inline int in(){ int X=0,w=0; char ch=0; while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int son[10]; bool end; }Trie[1600000];//这个大小上面算过了 int T,n,root,tot; char num[50]; bool insert(char t[],int l){//添加数字到字典树中 int o=root; for (int i=0;i<l;i++){ int ch=t[i]-'0'; if (!Trie[o].son[ch]) Trie[o].son[ch]=++tot; o=Trie[o].son[ch]; } if (Trie[o].end) return false;//判断字典树中是否存在这个数 Trie[o].end=true; return true; } int main(){ T=in(); while (T--){ memset(&Trie,0,sizeof(Trie));//每次要清空一下,因为数组太大了,所以memset可能会很慢 tot=0;//但是还是能过,泥萌可以试一下每次只把1~tot的清空 n=in(); while (n--){ scanf("%s",num); if (insert(num,strlen(num))) printf("%s ",num); } printf("\n"); } return 0; } ```