【蓝桥杯VIP】试题 历届试题 子串分值和(满分 Python解法+Java解法)
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
对于一个字符串 ,我们定义 的分值 为 中出现的不同的字符个数。例如f(“aba”)=2,f(“abc”)=3, f(“aaa”)=1。
现在给定一个字符串(S[0…n-1](长度为 n),请你计算对于所有 S 的非空子串 Si…j,f(S[i…j])的和是多少。
输入格式
输入一行包含一个由小写字母组成的字符串 S。
输出格式
输出一个整数表示答案。
样例输入
ababc
样例输出
28
样例说明
子串 f值
a 1
ab 2
aba 2
abab 2
ababc 3
b 1
ba 2
bab 2
babc 3
a 1
ab 2
abc 3
b 1
bc 2
c 1
评测用例规模与约定
对于 20% 的评测用例,1<=n<=10 ;
对于 40% 的评测用例,1<=n<=100 ;
对于 50% 的评测用例,1<=n<=1000 ;
对于 60% 的评测用例,1<=n<=10000 ;
对于所有评测用例,1<=n<=100000 。
思路:
当前元素提供的个数 等于 当前位置与末位置的差+1 乘以 当前位置与该元素上一次出现位置的差。
例如:
输入:ababc
输出:
a 1
ab 2
aba 2
abab 2
ababc 3
b 1
ba 2
bab 2
babc 3
a 1
ab 2
abc 3
b 1
bc 2
c 1
结合上例:
当前位置与末位置的差+1 因为: 该元素在当前位置以及之后的位置无论之后还有没有该元素,该元素都是只提供一次.
当前位置与该元素上一次出现位置的差 因为: 该元素在当前位置 以及在 该元素上一次出现的地方消失后的位置之间都要提供次数.
Python解法:
# 100分
list1=list(input())
list2=[-1 for i in range(26)]
count=0
for i in range(len(list1)):
index=ord(list1[i])-ord('a')
count+=(len(list1)-i)*(i-list2[index])
list2[index]=i
print(count)
Java解法:
// 100分
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner scan=new Scanner(System.in);
char[] arr1=scan.nextLine().toCharArray();
int[] arr2=new int[26];
long count=0; //必须要用 long,因为当输入数据太大时,就会超出 int的范围( -2^32~2^31 (-2147483648 ~ 2147483647))
int index;
long len=arr1.length; //当arr1.length太大时,必须要用long型保存
for(int i=0;i<arr2.length;i++){
arr2[i]=-1;
}
for(int i=0;i<arr1.length;i++){
index=arr1[i]-'a';
// count+=(arr1.length-i)*(i-arr2[index]); //错误:arr1.length是 int型,当arr1.length太大时,必须要用long型保存
count+=(len-i)*(i-arr2[index]);
arr2[index]=i;
}
System.out.println(count);
}
}