Eat Study Love

먹고 공부하고 사랑하라

Coding_Practice

Sum of Prefix Scores of Strings[Array,String,Trie,Counting]

eatplaylove 2024. 9. 25. 12:17

https://leetcode.com/problems/sum-of-prefix-scores-of-strings/description/?envType=daily-question&envId=2024-09-25

You are given an array words of size n consisting of non-empty strings.

We define the score of a string word as the number of strings words[i] such that word is a prefix of words[i].

  • For example, if words = ["a", "ab", "abc", "cab"], then the score of "ab" is 2, since "ab" is a prefix of both "ab" and "abc".

Return an array answer of size n where answer[i] is the sum of scores of every non-empty prefix of words[i].

Note that a string is considered as a prefix of itself.

 

Example 1:

Input: words = ["abc","ab","bc","b"]
Output: [5,4,3,2]
Explanation: The answer for each string is the following:
- "abc" has 3 prefixes: "a", "ab", and "abc".
- There are 2 strings with the prefix "a", 2 strings with the prefix "ab", and 1 string with the prefix "abc".
The total is answer[0] = 2 + 2 + 1 = 5.
- "ab" has 2 prefixes: "a" and "ab".
- There are 2 strings with the prefix "a", and 2 strings with the prefix "ab".
The total is answer[1] = 2 + 2 = 4.
- "bc" has 2 prefixes: "b" and "bc".
- There are 2 strings with the prefix "b", and 1 string with the prefix "bc".
The total is answer[2] = 2 + 1 = 3.
- "b" has 1 prefix: "b".
- There are 2 strings with the prefix "b".
The total is answer[3] = 2.

Example 2:

Input: words = ["abcd"]
Output: [4]
Explanation:
"abcd" has 4 prefixes: "a", "ab", "abc", and "abcd".
Each prefix has a score of one, so the total is answer[0] = 1 + 1 + 1 + 1 = 4.

 

Constraints:

  • 1 <= words.length <= 1000
  • 1 <= words[i].length <= 1000
  • words[i] consists of lowercase English letters.\

어제 풀었던 문제와 유사한 prefix 문제. 근데 이번엔 Hard 난이도다..

 

 

1. Python

class Solution:
    def sumPrefixScores(self, words: List[str]) -> List[int]:
        ans = []
        s = set()
        cnt = 0
        string = ""
        for word in words :
            # Save all prefix of words[i]
            for i in range(len(word)):
                string += word[i]
                s.add(string)
            # Calculate cnt
            for word2 in words :
                temp = word2
                while temp:
                    if temp in s :
                        cnt += 1
                    temp = temp[:-1]
            # update ans list
            ans.append(cnt)
            cnt = 0
            string = ""
            s.clear()
        return ans

간단한 예제는 통과가 되는데, 또 무지막지하게 긴 string들이 있는 test case에선 time limit이 걸린다.

아오 진짜...

 

답지를 보니까 Trie Node를 쓰라고 한다. 그래야 시간이 빨라진다고...

멀고도 험한 Data Structure의 세계이다.

class TrieNode:
    def __init__(self):
        self.children = {}
        self.score = 0

class Solution:
    def sumPrefixScores(self, words: List[str]) -> List[int]:
        root = TrieNode()
        
        # Build Trie with all words
        for word in words:
            node = root
            for char in word:
                if char not in node.children:
                    node.children[char] = TrieNode()
                node = node.children[char]
                node.score += 1
        
        # Calculate prefix scores for each word
        result = []
        for word in words:
            node = root
            total_score = 0
            for char in word:
                node = node.children[char]
                total_score += node.score
            result.append(total_score)
        
        return result

 

이해하고 나니까 뭔가 깰꼼했던 Data 구조이다.

이걸 이제 혼자 힘으로 C++로 옮겨보자.

C로 옮기는 건 언감생심!

 

혼자 힘 X, GPT Support 조금 받긴 했음.

 

 

2. C++

class Tree{
public:
    map<char,Tree*> m;
    int score;
    Tree():score(0){}
    ~Tree(){
        for(auto& pair : m){
            delete pair.second;
        }
    }
};
class Solution {
public:
    vector<int> sumPrefixScores(vector<string>& words) {
        Tree* root = new Tree();
        for(string word : words){
            Tree* node = root;
            for(char ch : word){
                if(node->m.find(ch)==node->m.end()){
                    node->m[ch] = new Tree();
                }
                node = node->m[ch];
                node->score += 1 ;
                }
            }
        vector<int> ans;
        for (string word : words) {
            Tree* node = root;
            int prefixScore = 0;
            for (char ch : word) {
                node = node->m[ch];
                prefixScore += node->score;
            }
            ans.push_back(prefixScore);
        }
        delete root;

        return ans;
    }
};