我的思路 :
在做这道题之前我因为做过和这类似的子串分值
所以感觉起来要容易很多。
对于这道题首先想到的是吧每个子串列出来然后对各个子串进行计算看它有多少个不同的字符,本来计算它有多少个不同的字符相对来说是这道题的主要难点(我感觉的),但是为毛要是学过C++中STL的set模板就会很简单(蓝桥杯明确指出可以用C++中STL标准模板库),因为set容器中本来就不容许有重复的元素,有重复的都算一个set容器用法。所以只要把所有的子串放到set容器中用size()算出它的大小,再把它们相加就可以得出结果。
这种方法我感觉代码应该是最方便的(各位谁有更好的方法可以留言一起讨论啊!)
代码如下:
#include<iostream>
using namespace std;
#include<set>
#include<string>
int main()
{
int ret = 0;
string s;
set<char> st;
cin >> s;
int n = s.size();
for (int i = 0; i < n; i++)
{
for (int j = i; j < n; j++)
{
for (int k = i; k <= j; k++)
{
st.insert(s[k]);
}
ret += st.size();
st.clear();
}
}
cout<<ret<<endl;
return 0;
}
这个我只是想到C++的set容器的用法,所以无聊写的,代码简单,但是也很容易超时。运用子串分值思路,可以这样来做:(为了避免被喷,还是乖乖的写出来,哈哈)
#include<iostream>
using namespace std;
#include<string>
int pre[1000001] = { 0 };
int last[100001] = { 0 };
int main()
{
long late[27];
int ret = 0;
string s;
cin >> s;
int n = s.size();
for (int i = 0; i <= 26; i++) late[i] = -1;
for (int i = 0; i < n; i++)
{
int d = s[i] - 'a';
pre[i] = late[d];
late[d] = i;
}
/*for (int i = 0; i <= 26; i++) late[i] = n;这个就用不到后一次出现的位置,
for (int i = n - 1; i > -1; i--) 因为若一个子串中第一个出现的字符算是
{ 那一个字符的话,后面的从到结尾都算,只要没碰到
int d = s[i] - 'a'; 它前一次出现的它就是老大
last[i] = late[d];
late[d] = i;
}*/
for (int i = 0; i < n; i++)
{
ret += long(i - pre[i]) * (n - i);
}
cout << ret << endl;
return 0;
}
我接下来到蓝桥杯 比赛这段时间尽量每天做一道往年题目或者找到合适的发上来,一方面监督自己,一方面求大佬指正,希望一起进步一起学习哈!!!