蓝桥杯:子串分值

题目描述

对于一个字符串 �S,我们定义 �S 的分值 �(�)f(S) 为 �S 中恰好出现一次的字符个数。例如 �(���)=1,�(���)=3,�(���)=0f(aba)=1,f(abc)=3,f(aaa)=0。

现在给定一个字符串 �0⋯�−1S0⋯n−1(长度为 �n,1≤�≤1051≤n≤105),请你计算对于所有 �S 的非空子串 ��⋯�(0≤�≤�<�)Sij(0≤ij<n),�(��⋯�)f(Sij) 的和是多少。

输入描述

输入一行包含一个由小写字母组成的字符串 �S

输出描述

输出一个整数表示答案。

输入输出样例

示例

输入
ababc
输出
21

运行限制

  • 最大运行时间:1s

  • 最大运行内存: 256M

题目分析:

题目给出了一个字符串,找出子串中一个字符出现一次的总个数。这道题刚看的时候想直接用暴力把他干掉。暴力思路就是直接套两层for循环,外循环代表着子串的有边界,内循环代表着子串的左边界。然后我们取出这个子串,我们在去找里面只出现一次的字符,然后我们把他们全部加起来就是最后结果。但是这个嘞会超时,只能拿到40分,不过在比赛的时候,如果想不到优化,这样子就可以,直接来一手骗分。优化的思路呢: 算出每个字符做出的贡献,先一层循环i,然后 在用两根指针right,left,left向左遍历,right向右遍历,当s[left]==s[i] 就退出向左和向右的遍历,然后这个相对应的字符做出的贡献就是(left+1)*(right+1),然后每个字符做出的贡献全部相加,就是结果了

AC代码:


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in) ;
        String s = scanner.next();

        char[] chars = s.toCharArray();

        int len = chars.length ;
        int res= 0 ;
        for(int  i =0 ;i<len;i++){
            int left =0 ;
            int right = 0 ;
            char c = chars[i];
            for (int  j = i-1 ; j>=0 && chars[j]!=c;j--){
                left++ ;
            }

            for (int k = i+1 ; k<len&& chars[k]!=c ; k++){
                right++ ;
            }

            res += (left+1)*(right+1) ;
        }


        System.out.println(res);

        scanner.close(); 


    }
}

猜你喜欢

转载自blog.csdn.net/weixin_54046648/article/details/129596855