字典树,又称trie树,主要用来统计字符串的前缀等等
HDU1671 and POJ 3630
题意是:输入的n串数字中 如果一个串 是 另一个串的前缀,则 YES
建立字典树,标记每个节点的状态:是儿子吗?是终点吗?如果在插入节点时遇到了终点 则包含,如果终点是儿子 则包含。
在添加的过程进行判断
结构体:
struct node { int nxt[10]; bool haveson,isleaf; }tre[maxn];
添加+判断
void add(int now,int x) //now是现在的位置,x是当前处理的字符位置 { if(x==len) { if(tre[now].isleaf||tre[now].haveson)ok=1; tre[now].isleaf=true; return; } if(tre[now].isleaf) {ok=1;return;} tre[now].haveson=true; int v=s[x]-'0'; if(!tre[now].nxt[v]) tre[now].nxt[v]=++cnt; //cnt是数组的下标 add(tre[now].nxt[v],x+1); }
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn=400050; struct node { int nxt[10]; bool haveson,isleaf; }tre[maxn]; char s[40]; int len,cnt,ok,n,t; void add(int now,int x) { if(x==len) { if(tre[now].isleaf||tre[now].haveson)ok=1; tre[now].isleaf=true; return; } if(tre[now].isleaf) {ok=1;return;} tre[now].haveson=true; int v=s[x]-'0'; if(!tre[now].nxt[v]) tre[now].nxt[v]=++cnt; add(tre[now].nxt[v],x+1); } int main() { scanf("%d",&t); while(t--) { memset(tre,0,sizeof(tre)); cnt=0; scanf("%d",&n); ok=0; while(n--) { scanf("%s",s); // scanf and cin 's speed 3 times len=strlen(s); if(!ok)add(0,0); } if(ok) printf("NO "); else printf("YES "); } return 0; }