蓝桥题解 499 子串分值 暴力 贡献法

2024-02-16 18:24:11 浏览数 (1)

蓝桥题解 499.子串分值

蓝桥杯题库 题目链接。

暴力解法

这题很容易想到暴力解题的思路,但是只能通过一半的测试用例。暴力解法代码如下:

代码语言:Java复制
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String str = scan.next();
        int len = str.length(), ans = 0;
        for (int i = 0; i < len; i  ) {
            for (int j = i; j < len; j  ) {
                String tmpStr = str.substring(i, j 1);
                ans = ans   f(tmpStr);
            }
        }
        System.out.println(ans);
        scan.close();
    }

    static int f(String str) {
        int len = str.length(), sum = 0;
        int[] s = new int[26];
        for (int i = 0; i < len; i  ) {
            s[str.charAt(i) - 'a']  ;
        }
        for (int i = 0; i < s.length; i  ) {
            if (s[i] == 1) {
                sum  ;
            }
        }
        return sum;
    }
}

贡献法

贡献法就是计算每个字符对最终结果能提供的贡献值,假设有字符串: xxaxxxaxxa。字符串中共有三个a,我们尝试计算一下第二个a对结果的贡献:

因为题目要求字符只出现一次的时候才会有贡献,那么第二个a在所有的子串情况下,有贡献的那一部分就要在第一个a后面,最后一个a前面的那一部分子串。如下图:

那么现在只需要考虑,在子串xxxaxx的子串中有多少种情况包含这个a,显而易见有如下12种:

我们可以得到其中的规律是:该字符的贡献度等于 (左边的距离 1) 乘 (右边的距离 1)。其中的距离指的是该字符到下一个相同字符的下标距离。具体代码如下:

Java代码

代码语言:Java复制
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        char[] s = scan.next().toCharArray();
        int len = s.length, ans = 0;

        for (int i = 0; i < len; i  ) {
            // 计算第i个字符的贡献度,l和r分别代表字符左右的边界距离
            int l = 0, r = 0;
            for (int j = i - 1; j >= 0 && s[j] != s[i]; j--) {
                l  ;
            }
            for (int j = i   1; j < len && s[j] != s[i]; j  ) {
                r  ;
            }
            ans = ans   (l 1) * (r 1);
        }
        System.out.println(ans);
        scan.close();
    }
}

0 人点赞