题目描述
如果一个字符串中不同字符的个数小于等于字符串中每个字符的出现个数,我们称为这个字符串具有多样性
如字符串"334"具有多样性,其中不同字符的数量为2,'3'出现了2次,'4'出现了一次,满足字符串多样性的定义
字符串"77"就不满足,其中不同字符的数量为1,'7'出现了两次,不满足字符串多样性的定义
现在我们给定一个有n个元素的字符串a(‘0’ <= a[i] <= ‘9’)。
请问这个数组有多少个子串具有多样性, 子串是指由字符串删掉前n个字符和后m个字符得到的字符串(n,m可以为0,但是n + m < n);
元素相同,位置不同的子串被看作不同的。
输入
第一行输入一个整数n代表字符串的长度(n <= 1e5).
第二行输入一个字符串。
输出
输出一个整数表示有多少个子串具有多样性。
样例输入
6
399996
样例输出
10
提示
具有多样性的字串分别有:
3 出现一次
39 出现一次
399 出现一次
9 出现四次
96 出现一次
996 出现一次
6 出现一次
- 这个题目穷举即可。
- 就是从每一位开始往后穷举,到后面的每一位截至构成一个新字符串,然后判断是否满足条件即可。
- 但是我觉得上面这个还是麻烦了,于是又优化了一下。我们从每一位开始的地方,成为一个新的字符串。这个新字符串往后遍历到结束符’\0’为止,在新字符串每往后遍历一位,其实在遍历的过程中又算子串。边往后走,准备10个桶,如果放进去那个桶的值为1,说明出现了新的字符。如果有一个桶里面的值大于了出现不同字符个数,说明这个字符串不具备多样性。
- 往后走的同时前面不同字符个数要保留,而且还要记录最大的桶的值,往后面刷新最大桶。判断这个最大桶是否大于不同字符即可。
代码如下:
#include<stdio.h>
#define N 100010
char a[N];
long long seek(char s[])
{
int a[15]={0},i,j,count=0,max=0;
long long sum=0;
for(i=0;s[i];i++)
{
a[s[i]-'0']++;
if(a[s[i]-'0']==1)
{
count++;
}
if(max<a[s[i]-'0']) max=a[s[i]-'0'];
if(max<=count) sum++;
}
return sum;
}
int main()
{
int n,i;
long long sum=0;
scanf("%d\n",&n);
gets(a);
for(i=0;a[i];i++)
{
sum+=seek(a+i);
}
printf("%lld\n",sum);
return 0;
}