计蒜客 字典树 糟糕的bug



题目来源:计蒜客https://www.jisuanke.com/minicourse/812/42071

蒜头君作为蒜厂的工程师,在开发网站时不小心写出了一个 Bug:当用户输入密码时,如果既和自己的密码一致,也同时是另一个用户密码的 前缀 时,用户会跳转到 404 页。

然而蒜头君坚称:我们的用户那么少,怎么可能触发这个 Bug……

机智的你,能不能帮蒜头君确认一下这个 Bug 到底会不会触发呢?

样例输入

第一行输入一个整数n(1n233333),表示蒜厂网站的用户数。接下来一共 n 行,每行一个由小写字母a-z组成的字符串,长度不超过 10,表示每个用户的密码。蒜厂的数据库容量太小,所有密码长度加起来小于 466666

样例输出

如果触发了 Bug 则输出一行Bug!,否则输出一行Good Luck!

样例输入1

3
abc
abcdef
cdef

样例输出1

Bug!

样例输入2

3
abc
bcd
cde

样例输出2

Good Luck!


题目类型就是串匹配,找前缀,多串情况下,很应该想到前缀树,也称为Trie树。

我们要注意的地方是 本身Find函数查找密码本身过程中一定会返回1 我们要手动返回0

第二 因为一定能找到 所以在find函数中 我手动注释了两个if 因为不会除法(这题的小细节


#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;


const int MAX_N = 466670;
const int MAX_C  = 26;
char s[233335][15];
struct Trie{
    int *ch[MAX_N];
    int tot;
    int cnt[MAX_N];


    void init(){
       tot = 0;
       memset(cnt,0,sizeof(cnt));
       memset(ch,0,sizeof(ch));
    }


    void Insert(char *str){
       int p = 0;
       for(int i=0;str[i];++i){
        if(ch[p]==NULL){
            ch[p] = new int[MAX_C];
            memset(ch[p],-1,sizeof(int) * MAX_C);
        }
        if(ch[p][str[i]-'a']==-1){
            ch[p][str[i]-'a']=++tot;
        }
        p = ch[p][str[i]-'a'];
       }
       cnt[p]++;
    }


    int Find(char *str){
       int p = 0;
       for(int i = 0;str[i];++i){
       if(cnt[p]!= 0 && str[i]) return 1;
       //if(ch[p]==NULL) return 0;
       //if(ch[p][str[i]-'a']==-1) return 0;
        p = ch[p][str[i]-'a'];
       }
       return 0;
    }


};


Trie trie;


int main(){
   int t;
   scanf("%d",&t);
   //sgetchar();
   bool ans = false;
   for(int i =0;i<t;++i){
    scanf("%s",s[i]);
    trie.Insert(s[i]);


   }
   for ( int i = 0 ; i < t ; ++ i ) {
        if ( trie.Find(s[i]) ) {
            ans = true;
        }
    }
    if ( ans ) {
        puts("Bug!");
    } else {
        puts("Good Luck!");
    }
   return 0;
}

猜你喜欢

转载自blog.csdn.net/heucodesong/article/details/80588943