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.
Note: 0 <= S.length <= 10000
.
解题思路:
解法一:
时间复杂度O(N^2);
class Solution {
public:
int uniqueLetterString(string S)
{
unordered_map<int , unordered_set<char>> uniquel , repeatl ;
long res = 0 ;
for(int i = 0 ; i < S.size() ; ++i)
{
res++;
for(int j = 0 ; j < i ; ++j)
{
if(uniquel[j].count(S[i]))
{
uniquel[j].erase(S[i]) ;
repeatl[j].insert(S[i]) ;
}
else
{
if(!repeatl[j].count(S[i])) uniquel[j].insert(S[i]) ;
}
res += uniquel[j].size() ;
}
uniquel[i].insert(S[i]) ;
}
return res ;
}
};
解法二:
在任何子串中,只有出现一次的字符才对最终的结果起作用。假设输入的S为 XXXAXXXXAXXAXXXXX,X表示其他任意字符,现在我们来计算蓝A对最后的输出贡献了多少,很显然在两个红A之间的子串中,只要是包括蓝A的子串都有蓝A的贡献,如果第一个红A到蓝A之间的字符数量是L,蓝A到第二个红A之间的字符数量是R,那么蓝A的贡献就是 L + R + L*R + 1 ,其中L表示蓝A与左边字符组成的子串数量,R为与右边的,L*R为同时与左右结合,1表示不与任何字符结合。所有只有找出所有字符左右两边相同字符出现的位置,即可计算出最终的答案
时间复杂度O(N) ;
class Solution {
public:
int uniqueLetterString(string S)
{
int n = S.size() ;
vector<vector<int>> letter(26 , vector<int>()) ;
long res = 0 ;
for(int i = 0 ; i < n ; i++)
{
letter[S[i] - 'A'].push_back(i) ;
}
for(int i = 0 ; i < 26 ; ++i)
{
if(letter[i].empty()) continue ;
int left = -1 , now , right , L , R ;
for(int j = 0 ; j < letter[i].size(); ++j)
{
now = letter[i][j] ;
if(j == letter[i].size() - 1)
{
right = n ;
}
else
{
right = letter[i][j + 1] ;
}
L = now - left - 1 , R = right - now - 1 ;
res += L + R + L * R + 1 ;
left = now ;
}
}
return res ;
}
};