当前位置: 代码迷 >> 综合 >> Tire:电话列表
  详细解决方案

Tire:电话列表

热度:7   发布时间:2023-12-22 13:59:16.0

题目链接:https://www.acwing.com/problem/content/163/
题意:给出一个电话列表,如果列表中存在其中一个号码是另一个号码的前缀这一情况,那么就称这个电话列表是不兼容的。
假设电话列表如下:
·Emergency 911
·Alice 97 625 999
·Bob 91 12 54 26
在此例中,报警电话号码(911)为Bob电话号码(91 12 54 26)的前缀,所以该列表不兼容。
数据范围
1≤t≤40,
1≤n≤10000
输入样例:
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
输出样例:
NO
YES
思路:显然这个题用tire是最简单方便的方法了,总共就两种情况:1,是否有一个串是当前串的前缀:遍历过程中是否出现过结尾标准 2,当前串是否是其他串的前缀:在结尾前是否开过新的节点。
代码实现:

#include<iostream>
#include<cstring>
#include<algorithm>using namespace std;
const int N = 1e5 + 5;int n;
int son[N][10], idx;
bool f[N];
char str[N];int insert(char *str)
{
    int p = 0;bool is_match = 0;bool has_new_node = 0;for(int i = 0; str[i]; i ++ ){
    int u = str[i] - '0';//如果没有这个节点就创建一个新节点if(!son[p][u]){
    son[p][u] = ++ idx;has_new_node = 1;}p = son[p][u];//如果有节点标准表示有其他串是当前串的前缀if(f[p]) is_match = 1;}f[p] = 1;//在插入新串的时候如果没有发现结束标准并且创建了新节点才表示没有前缀匹配return !is_match && has_new_node ;
}int main()
{
    int t;cin >> t;while(t -- ){
    cin >> n;memset(son, 0, sizeof son);memset(f, 0, sizeof f);idx = 0;bool res = 1;for(int i = 0; i < n; i ++ ){
    cin >> str;if(!insert(str))res = 0;}if(res) cout << "YES" << endl;else cout << "NO" << endl;}return 0;
}