AcWing 161. 电话列表 (trie)打卡

给出一个电话列表,如果列表中存在其中一个号码是另一个号码的前缀这一情况,那么就称这个电话列表是不兼容的。

假设电话列表如下:

·Emergency 911
·Alice 97 625 999
·Bob 91 12 54 26

在此例中,报警电话号码(911)为Bob电话号码(91 12 54 26)的前缀,所以该列表不兼容。

输入格式

第一行输入整数t,表示测试用例数量。

对于每个测试用例,第一行输入整数n,表示电话号码数量。

接下来n行,每行输入一个电话号码,号码内数字之间无空格,电话号码不超过10位。

输出格式

对于每个测试用例,如果电话列表兼容,则输出”YES”。

否则,输出”NO”。

数据范围

1t401≤t≤40,
1n100001≤n≤10000

输入样例:

2
3
911
97625999
91125426
5
113
12340
123440
12345
98346

输出样例:

NO
YES


题意:让你判断电话列表有没有矛盾
思路:前缀判断,我们用trie,首先我们存下每个串最后出现的位置+1,然后后面的字符串遍历的时候,如果路径上有过+1,说明有字符串在这里终止成为了这个串的前缀,所以为NO
因为判断时判断前面的能不能成为后面串的前缀,所以我们首先按照长度从小到大排序、


#include<bits/stdc++.h>
#define maxn 100005
#define mod 1000000007
using namespace std;
int ch[maxn][10];
int dp[maxn];
string str[maxn];
int tot=1;
int insert(string s){
    int p=1;
    for(int i=0;i<s.size();i++){
        int k=s[i]-'0';
        if(ch[p][k]==0) ch[p][k]=++tot;
        p=ch[p][k]; 
        //dp[p]++;
        if(dp[p]) return 0; 
    }
    dp[p]++;
    return 1;
}
int cmp(string x,string y){
    return x.size()<y.size(); 
}
int main(){
    int t,n;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        tot=1;
        memset(ch,0,sizeof(ch));
        memset(dp,0,sizeof(dp));
        int flag=1;
        for(int i=0;i<n;i++){
            cin>>str[i];
        }
        sort(str,str+n,cmp);
        for(int i=0;i<n;i++){
            int k=insert(str[i]);
            if(k==0){
                flag=0;
            }
        }
        if(flag) printf("YES\n");
        else printf("NO\n"); 
    } 
} 
 

猜你喜欢

转载自www.cnblogs.com/Lis-/p/10982245.html