Skip to content

2262. Total Appeal of A String 👍

Approach 1: DP

  • Time: $O(n)$
  • Space: $O(26) = O(1)$
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
 public:
  long long appealSum(string s) {
    long ans = 0;
    // the total appeal of all substrings ending in the index so far
    int dp = 0;
    vector<int> lastSeen(26, -1);

    for (int i = 0; i < s.length(); ++i) {
      //   the total appeal of all substrings ending in s[i]
      // = the total appeal of all substrings ending in s[i - 1]
      // + the number of substrings ending in s[i] that contain only this s[i]
      const int c = s[i] - 'a';
      dp += i - lastSeen[c];
      ans += dp;
      lastSeen[c] = i;
    }

    return ans;
  }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
  public long appealSum(String s) {
    long ans = 0;
    // the total appeal of all substrings ending in the index so far
    int dp = 0;
    int[] lastSeen = new int[26];
    Arrays.fill(lastSeen, -1);

    for (int i = 0; i < s.length(); ++i) {
      //   the total appeal of all substrings ending in s[i]
      // = the total appeal of all substrings ending in s[i - 1]
      // + the number of substrings ending in s[i] that contain only this s[i]
      final int c = s.charAt(i) - 'a';
      dp += i - lastSeen[c];
      ans += dp;
      lastSeen[c] = i;
    }

    return ans;
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution:
  def appealSum(self, s: str) -> int:
    ans = 0
    # the total appeal of all substrings ending in the index so far
    dp = 0
    lastSeen = {}

    for i, c in enumerate(s):
      #   the total appeal of all substrings ending in s[i]
      # = the total appeal of all substrings ending in s[i - 1]
      # + the number of substrings ending in s[i] that contain only this s[i]
      dp += i - lastSeen.get(c, -1)
      ans += dp
      lastSeen[c] = i

    return ans

Approach 2: Combinatorics

  • Time: $O(n)$
  • Space: $O(26) = O(1)$
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution {
 public:
  long long appealSum(string s) {
    const int n = s.length();
    long ans = 0;
    vector<int> lastSeen(26, -1);

    for (int i = 0; i < n; ++i) {
      const int c = s[i] - 'a';
      ans += (i - lastSeen[c]) * (n - i);
      lastSeen[c] = i;
    }

    return ans;
  }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution {
  public long appealSum(String s) {
    final int n = s.length();
    long ans = 0;
    int[] lastSeen = new int[26];
    Arrays.fill(lastSeen, -1);

    for (int i = 0; i < n; ++i) {
      final int c = s.charAt(i) - 'a';
      ans += (i - lastSeen[c]) * (n - i);
      lastSeen[c] = i;
    }

    return ans;
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Solution:
  def appealSum(self, s: str) -> int:
    ans = 0
    lastSeen = {}

    for i, c in enumerate(s):
      ans += (i - lastSeen.get(c, -1)) * (len(s) - i)
      lastSeen[c] = i

    return ans