码迷,mamicode.com
首页 > 其他好文 > 详细

LeetCode题828 —— Unique Letter String

时间:2018-09-27 01:54:00      阅读:285      评论:0      收藏:0      [点我收藏+]

标签:NPU   exp   out   exactly   uniq   string   except   不同   逆转   

https://leetcode.com/problems/unique-letter-string/description/

A character is unique in string S if it occurs exactly once in it.

For example, in string S = "LETTER", the only unique characters are "L" and "R".

Let‘s define UNIQ(S) as the number of unique characters in string S.

For example, UNIQ("LETTER") =  2.

Given a string S with only uppercases, calculate the sum of UNIQ(substring) over all non-empty substrings of S.

If there are two or more equal substrings at different positions in S, we consider them different.

Since the answer can be very large, return the answer modulo 10 ^ 9 + 7.

Example 1:

Input: "ABC"
Output: 10
Explanation: All possible substrings are: "A","B","C","AB","BC" and "ABC".
Evey substring is composed with only unique letters.
Sum of lengths of all substring is 1 + 1 + 1 + 2 + 2 + 3 = 10

Example 2:

Input: "ABA"
Output: 8
Explanation: The same as example 1, except uni("ABA") = 1.

分析

看了discuss,大神的思维和我等常人就是不一样,跪服。首先以字符串XAXAXXAX为例,如果将第二个 A 变成唯一的character的话,只可能时某个唯一的substring包含了这个A。比如:

We can take "XA(XAXX)AX" and between "()" is our substring.

利用这种方式,可以使得第二个A成为唯一的character,那么从上可知我们要做的是:

We can see here, to make the second "A" counted as a uniq character, we need to:

  1. insert "(" somewhere between the first and second A
  2. insert ")" somewhere between the second and third A

For step 1 we have "A(XA" and "AX(A", 2 possibility.
For step 2 we have "A)XXA""AX)XA" and "AXX)A", 3 possibilities.

So there are in total 2 * 3 = 6 ways to make the second A a unique character in a substring.
In other words, there are only 6 substring, in which this A contribute 1 point as unique string.

现在逆转下思维,一开始的思维是在原字符串的所有子串中寻找可能的唯一的character,我们现在就直接在S中来计算每个字符,看看对于每个unique char总公有多少种不同的找法。换而言之就是,对于S中的每个字符,如果他作为unique char的话,那么包含他的substring的范围是在前一个相同字符以及后一个相同字符这个区间内找的(参见上面的A),将所有可能的substring数量加起来即可,很有趣的逆向思维。

Explanation:

  1. index[26][2] record last two occurrence index for every upper characters.
  2. Initialise all values in index to -1.
  3. Loop on string S, for every character c, update its last two occurrence index to index[c].
  4. Count when loop. For example, if "A" appears twice at index 3, 6, 9 seperately, we need to count:
    • For the first "A": (6-3) * (3-(-1))"
    • For the second "A": (9-6) * (6-3)"
    • For the third "A": (N-9) * (9-6)"

代码

  public int uniqueLetterString(String S) {
    int[][] index = new int[26][2];
    for (int i = 0; i < 26; ++i) Arrays.fill(index[i], -1);
    long res = 0, N = S.length(), mod = (int) Math.pow(10, 9) + 7;
    for (int i = 0; i < N; i++) {
      int c = S.charAt(i) - ‘A‘;
      res = res + (i - index[c][1]) * (index[c][1] - index[c][0]);
      index[c] = new int[]{index[c][1], i};
    }
  // 计算最后的c
for (int c = 0; c < 26; ++c) res = res + (N - index[c][1]) * (index[c][1] - index[c][0]); return (int) (res % mod); }

 

LeetCode题828 —— Unique Letter String

标签:NPU   exp   out   exactly   uniq   string   except   不同   逆转   

原文地址:https://www.cnblogs.com/f91og/p/9710808.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!