https://leetcode.com/problems/unique-letter-string/description/app
A character is unique in string S
if it occurs exactly once in it.ide
For example, in string S = "LETTER"
, the only unique characters are "L"
and "R"
.oop
Let's define UNIQ(S)
as the number of unique characters in string S
.this
For example, UNIQ("LETTER") = 2
.spa
Given a string S
with only uppercases, calculate the sum of UNIQ(substring)
over all non-empty substrings of S
.code
If there are two or more equal substrings at different positions in S
, we consider them different.blog
Since the answer can be very large, return the answer modulo 10 ^ 9 + 7
.ip
Example 1:leetcode
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:
"("
somewhere between the first and second A
")"
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:
index[26][2]
record last two occurrence index for every upper characters.index
to -1
.c
, update its last two occurrence index to index[c]
.代码
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); }