Problem Description
Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let’s say the phone catalogue listed these numbers:
- Emergency 911
- Alice 97 625 999
- Bob 91 12 54 26
In this case, it’s not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob’s phone number. So this list would not be consistent.
Input
The first line of input gives a single integer, 1 <= t <= 40, the number of test cases. Each test case starts with n, the number of phone numbers, on a separate line, 1 <= n <= 10000. Then follows n lines with one unique phone number on each line. A phone number is a sequence of at most ten digits.
Output
For each test case, output “YES” if the list is consistent, or “NO” otherwise.
Sample Input
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
Sample Output
NO
YES
| 题意:判断当前字符串是否不为其他字符串的前缀 |
思路(字典树):
模板题,套字典树的板子就行了。只需要在search函数做一点小修改,如果当前访问到color[p]==1的点,说明跑完了别的字符串,存在当前子串的字符串,返回真,若跑到trie[p][c]为空,说明不含有这样的前缀,返回假。最后跑完当前字符串都没发现有空的,说明当前字符串是其他字符串的前缀,函数结束前返回真
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include <stack>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define maxn 100000+500
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int maxm = 100000+5;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') ch = getchar();while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x; }
const int MAX_NODE = 100000 + 10;
const int CHARSET = 12;
int trie[MAX_NODE][CHARSET] = {0};
int color[MAX_NODE] = {0};
int k = 1;
void insert(string w)
{
int len = w.size();
int p = 0;
for(int i=0; i<len; i++)
{
int c = w[i] - '0';
if(!trie[p][c]) //看看第p位置往下有没有以c开头的字符串
{
trie[p][c] = k; //没有的话就新增标记
k++; //更新
}
p = trie[p][c]; //p指针往下移动
}
color[p] = 1;
}
int search(string s)
{
int len = s.size();
int p = 0;
for(int i=0; i<len; i++)
{
int c = s[i] - '0';
if(!trie[p][c]) return 0; //如果没遍历完就到头了,说明不存在
p = trie[p][c]; //否则往下走
if(color[p]) return 1; //对方是当前前缀
}
return 1; //当前是对方前缀
}
string s;
int main()
{
int kase;
scanf("%d",&kase);
while(kase--)
{
memset(trie,0,sizeof(trie));
memset(color,0,sizeof(color));
k = 1;
map<string,int> vis;
int n;
scanf("%d",&n) ;int flag = 1;
while(n--)
{
cin>>s;
if(search(s)) flag = 0;
insert(s);
}
if(flag) cout<<"YES"<<'\n';
else cout<<"NO"<<'\n';
}
return 0;
}

该博客讨论了一道编程题目,涉及检查电话号码列表是否一致,即没有号码是另一个号码的前缀。通过使用字典树(Trie)模板来解决此问题,博客提供了思路和样例输入输出,并解释了如何修改搜索函数来判断是否存在前缀关系。


被折叠的 条评论
为什么被折叠?



