6183. 字符串的前缀分数和(每日一难phase2--day18)

6183. 字符串的前缀分数和

给你一个长度为 n 的数组 words ,该数组由 非空 字符串组成。

定义字符串 word 的 分数 等于以 word 作为 前缀 的 words[i] 的数目。

例如,如果 words = [“a”, “ab”, “abc”, “cab”] ,那么 “ab” 的分数是 2 ,因为 “ab” 是 “ab” 和 “abc” 的一个前缀。
返回一个长度为 n 的数组 answer ,其中 answer[i] 是 words[i] 的每个非空前缀的分数 总和

注意:字符串视作它自身的一个前缀。

示例 1:

输入:words = [“abc”,“ab”,“bc”,“b”]
输出:[5,4,3,2]
解释:对应每个字符串的答案如下:

  • “abc” 有 3 个前缀:“a”、“ab” 和 “abc” 。
  • 2 个字符串的前缀为 “a” ,2 个字符串的前缀为 “ab” ,1 个字符串的前缀为 “abc” 。 总计 answer[0] = 2 + 2 + 1 = 5 。
  • “ab” 有 2 个前缀:“a” 和 “ab” 。
  • 2 个字符串的前缀为 “a” ,2 个字符串的前缀为 “ab” 。 总计 answer[1] = 2 + 2 = 4 。
  • “bc” 有 2 个前缀:“b” 和 “bc” 。
  • 2 个字符串的前缀为 “b” ,1 个字符串的前缀为 “bc” 。 总计 answer[2] = 2 + 1 = 3 。
  • “b” 有 1 个前缀:“b”。
  • 2 个字符串的前缀为 “b” 。 总计 answer[3] = 2 。

示例 2:

输入:words = [“abcd”]
输出:[4]
解释: “abcd” 有 4 个前缀 “a”、“ab”、“abc” 和 “abcd”。每个前缀的分数都是 1 ,总计 answer[0] = 1 + 1 + 1 + 1 = 4 。

提示:

1 <= words.length <= 1000
1 <= words[i].length <= 1000 words[i]
由小写英文字母组成

解析:

可以使用字典树,做法如下:

  • 将所有字符串加入字典树,每个节点还需要维护一个分数,代表有多少字符串经过该结点(也就是该字符串可以做多少字符串的前缀);
  • 同时,该节点还需要在字符串的末尾标记该字符串的id;
  • 然后dfs字典树中所有路径
    在这里插入图片描述
    代码参考

代码:

class Solution {
    struct Node{
        Node* son[26]{};
        vector<int> ids;
        int scores;
    };
public:

    // 遍历每一个节点
    vector<int> ans;
    void dfs(Node* root,int sum){
        if(!root)   
            return;
        // sum记录一条路径上各节点总和
        sum+=root->scores;
        // 如果该节点为一个字符串的最后一个结点,就给该点赋值
        for(auto a :root->ids){
            ans[a]+=sum;
        }
        for(auto a:root->son){
            dfs(a,sum);
        }
    }

    vector<int> sumPrefixScores(vector<string>& s) {
        int n=s.size();

        // 字典树根节点
        Node* root=new Node();
        for(int i=0;i<n;i++){
            Node* cur=root;
            // 将字符串插入字典树
            for(char c:s[i]){
                c-='a';
                if(cur->son[c]==nullptr)
                    cur->son[c]=new Node();
                cur=cur->son[c];
                ++cur->scores;
            }
            // 在字符串末尾处放入以该节点为结尾的字符串下标
            cur->ids.push_back(i);
        }
        ans.resize(n);
        // 遍历字符串上的每一条路径
        dfs(root,0);
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值