题目来源:计蒜客https://www.jisuanke.com/minicourse/812/42071
蒜头君作为蒜厂的工程师,在开发网站时不小心写出了一个 Bug:当用户输入密码时,如果既和自己的密码一致,也同时是另一个用户密码的 前缀 时,用户会跳转到 404 页。
然而蒜头君坚称:我们的用户那么少,怎么可能触发这个 Bug……
机智的你,能不能帮蒜头君确认一下这个 Bug 到底会不会触发呢?
样例输入
第一行输入一个整数n(1≤n≤233333),表示蒜厂网站的用户数。接下来一共 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树。
这里首先需要把所有串都读下来插入之后再进行匹配,因为你不能确定一定是前面的是后面的前缀。
对cnt处理的时候 也不能像这个Trie树处理一样。本题这里需要找一个串是另一个串的前缀,
所以,应该等一个串读完了,再进行标记。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define MAX_N 2333430 #define MAX_C 26 struct Trie{ int *ch[MAX_N]; int tot; int cnt[MAX_N]; Trie() { tot = 0; memset( ch, 0, sizeof(ch) ); memset( cnt, 0, sizeof(cnt) ); } void insert( const 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] ++;// 这里记录完整的串 而不是前缀 } bool find( const char* str ) { int p = 0; for ( int i = 0 ; str[i] ; ++ i ) { if ( cnt[p] != 0 && str[i] ) return true; if ( ch[p] == NULL ) return 0; if ( ch[p][str[i]-'a'] == -1 ) return 0; p = ch[p][str[i]-'a']; } return false; } }; char s[MAX_N][15]; Trie trie; int main() { int n; scanf( "%d", &n ); getchar(); bool ans = false; for ( int i = 0 ; i < n ; ++ i ) { scanf( "%s", s[i] ); getchar(); trie.insert(s[i]); } for ( int i = 0 ; i < n ; ++ i ) { if ( trie.find(s[i]) ) { ans = true; } } if ( ans ) { puts("Bug!"); } else { puts("Good Luck!"); } return 0; }