首先上报一下自己暴力做的,可能也就能过50%得数据,后面显然是超时了。
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<sstream>
#include<map>
#include<limits.h>
#include<set>
#define MAX 100010
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
LL n, m, counts, num;
string s;
map<char, int>maps;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> s;
counts += s.size();
num = 2;
for (int i = 0; i < s.size()-(num-1); i++) {
string buf = s.substr(i,num);
maps.clear();
for (int j = 0; j < buf.size(); j++) {
maps[buf[j]]++;
}
for (int j = 0; j < buf.size(); j++) {
if (maps[buf[j]] == 1)
counts++;
}
if (i == s.size() - num)
{
i = -1;
num++;
}
}
cout << counts << endl;
return 0;
}
这里解释一下自己的做法:
首先看到这些字符串的子集都是连续子集,所以我们可以用滑动窗口的方法进行做,可以规定每次滑动窗口的大小,再在这个滑动窗口里面统计不同的字母。
这里统计字母的时候用到了map容器,用来记录每个字母的数目。在后面的判断当中,我们可以在个数是1的情况下更新当前子集不同字符的个数。这样一直进行下去就行了。时间复杂度最好是
O(N2),所以并不能过数据。
然后就学到了一种方法叫做贡献法。这里运用贡献的话也就是说当我们碰到一个字母之后,我们看看除了没有这个字母之外的子集我们能贡献多少个子集。
比如,a....a....a,其中.都是不为a的字符,那么从中间那个a开始(我们只考虑有一个a的情况)这样我们就会有(6-1)*(11-6)种子集,这样的话我们每个位置都可以这样枚举,然后算出贡献的子集数。
那么,就按照这个思路进行编写程序就行了。
注意:数据范围上我们需要在最后结果上用long long类型,这样才能保证数据不超过int。
上代码:
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<sstream>
#include<map>
#include<limits.h>
#include<set>
#define MAX 100010
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
LL n, m, counts, num;
char s[MAX];
int l[MAX], r[MAX], p[MAX];
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> s + 1;
int n = strlen(s + 1);
_for(i, 1, n+1) {
int tmp = s[i] - 'a';//字母代表的数字
l[i] = p[tmp];
p[tmp] = i;
}
_for(i, 0, 26)p[i] = n + 1;
for (int i = n; i; i--) {
int tmp = s[i] - 'a';
r[i] = p[tmp];
p[tmp] = i;
}
for (int i = 1; i <= n; i++)
counts += (LL)(i - l[i]) * (r[i] - i);
cout << counts << endl;
return 0;
}