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); }