【HDU 1671】 Phone List 字典樹 模板題

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:

  1. Emergency 911
  2. Alice 97 625 999
  3. 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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章