--- title: "电话列表" created: 2025-11-28 tags: - 算法 --- # 电话列表 ## 题目 [电话列表](https://www.acwing.com/problem/content/description/163/) ![[image-77989b8f.png]] ## 思路分析 判前缀子串很明显trie树 在插入的时候就可以做判断 假设已经插入了 i个字符串,现在要插入一个字符串 str 那么此时 str产生不兼容的方式只有两种 str是前 i个已插入字符串的前缀 前 i个字符串中存在 str的前缀 对于第一种情况, str这个字符串在 trie中一定已经存在,所以一定不需要新开节点。如果开了新节点 就说明不满足1情况 所以用一个标记 对于第二种情况, 在插入 str时一定会遇到一个节点被标记为了终点 对于每一个点都判断是否是某个串的终点 如果存在 说明满足2情况 ## 代码实现 ```cpp #include using namespace std; const int N=100010; int son[N][10]; int idx; bool exist[N]; char str[10010]; int n,T; bool insert(char *str) { int p=0; bool case_1=false;//是否新开结点 新开表示该串不是其他串的子串 bool case_2=false;//路上是否遇到其他串的结束标记 遇到说明包含其他串 for(int i=0;str[i];i++) { int u=str[i]-'0'; if(!son[p][u]){ son[p][u]=++idx; case_1=true; } p=son[p][u]; if(exist[p]) case_2=true; } exist[p]=true; return case_1 && !case_2; } int main() { cin>>T; while(T--) { cin>>n; memset(son,0,sizeof son); memset(exist,false,sizeof exist); idx=0; bool res=true; for(int i=0;i>str; if(!insert(str)) res=false; } if(res) cout<<"YES"<