P1481 魔族密码

题目来自洛谷网站:

P1481 魔族密码_第1张图片

字典树trie思路:

题目要求我们找到最长的词链,题目告诉我们:如果在一个由一个词或多个词组成的表中,除了最后一个以外,每个单词都被其后的一个单词所包含,即前一个单词是后一个单词的前缀,则称词表为一个词链。
①将输入的字符串存入字典树中,在存入的过程中,我们用dp数组来记录以这个字符串末尾结尾的字符串链接了几个字符串。
②也就是说,题目的最长词链一定是树上最长的支,当我们找完了这个字符串能够链接几个字符串。遍历完了这个字符串,我们要加上这个字符串本身的长度。这就是这条支的答案。在和答案比较,找到最大的答案。

字典树trie代码:

#include
#define int long long
using namespace std;
const int N = 2020;

int n;
//trie表示N层最多27分支的字典树 
//idx表示编号
int trie[N][27], idx;
//存的是每个单词以什么结尾
int dp[N];
int ans;

void add(string x){
    //指针p从0开始
    int p = 0;
    //储存这一条分支链接了几个单词
    int ssmax = 0;
    for(int i = 0; i < x.size(); i++){
        //得到x的第i个字符的映射值
        int j = x[i] - 'a';
        //p节点下没有 x[i] 字符,因此创造这个分支
        if(!trie[p][j]){
            trie[p][j] = ++idx;
        }
        p = trie[p][j];
        
        //判断一下新存入的单词的前缀和前一个单词是否相同
        //如果相同,那么新存入的单词就链接了1个单词 更新ssmax
        ssmax = max(ssmax, dp[p]);
    }
    //当循环结束,代表这个单词已经全部存入到字典树中
    //那么这个单词结尾p,dp[i]链接数要加上(自己+1)
    dp[p] = ssmax + 1;
    //找到最大的链接数
    ans = max(ans, dp[p]);
    
}

signed main(){
    cin >> n;
    for(int i = 0; i <= n; i++){
        string x; cin >> x;
        //将x存入字典树中
        add(x);
    }
    cout << ans << endl;
    return 0;
}

你可能感兴趣的:(算法)