LeetCode題828 —— Unique Letter String
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:
- insert
"("
somewhere between the first and secondA
- insert
")"
somewhere between the second and thirdA
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:
index[26][2]
record last two occurrence index for every upper characters.- Initialise all values in
index
to-1
. - Loop on string S, for every character
c
, update its last two occurrence index toindex[c]
. - 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