题目描述:
对于一个字符串S,我们定义S 的分值 f(S) 为S中恰好出现一次的字符个数。例如f (”aba”) = 2,f (”abc”) = 3, f (”aaa”) = 1。
现在给定一个字符串S[0…n-1](长度为n),请你计算对于所有S的非空子串S[i…j](0 ≤ i ≤ j < n), f (S[i… j]) 的和是多少。
解题思路:
原理:只有当字母个数在子串中个数>0才会有贡献度。
从字符左右两边出发
- 往左直到走到第一个,每走一次left++
- 往右走到与自己相同的字符停止,每次right++
贡献度 = (left+1) * (right+1)
拿ababd举例:
- 从第一个a开始:左边没有,右边走一步,所以 (0+1)*(1+1)=2
- 到第二个b:左边1个,右边1个,(1+1)*(1+1)=4
- 左边2个,右边2个,(2+1)*(2+1)=9
- 左边3个,右边1个,(3+1)*(1+1)=8
- 左边4个,右边0个,(4+1)*(0+1)=5
最终:28
代码:
暴力代码(50%):
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
public class 第十一届_子串分值和 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
String str = sc.next();
int sum = 0;
for(int i = 0; i<str.length(); i++) { // 起点
for(int j = i; j<str.length(); j++) { // 终点
HashSet set = new HashSet();
for(int k = i; k<=j; k++) {
// System.out.print(str.charAt(k));
set.add(str.charAt(k));
}
// System.out.println(set + " " + set.size());
sum += set.size();
}
}
System.out.print(sum);
}
}
AC代码:
package lanqiao;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.next();
char[] ch = str.toCharArray();
long res = 0;
for(int i = 0; i < ch.length; i++) {
int left = 0;
int right = 0;
// 往左
for(int j = i-1; j>=0 ; j--) {
left++;
}
// 往右
for(int j = i+1; j<ch.length && ch[j] != ch[i]; j++) {
right++;
}
res += (long)(left+1)*(right+1);
}
System.out.print(res);
}
}