【算法】【字符串】关联子串

1  题目

给定两个字符串str1和str2,如果字符串str1中的字符,经过排列组合后的字符串中,只要有一个字符串是str2的子串,则认为str1是str2的关联子串。

若str1是str2的关联子串,请返回子串在str2的起始位置;

若不是关联子串,则返回-1。

输入描述:输入两个字符串,分别为题目中描述的str1、str2。

备注:输入的字符串只包含小写字母;两个字符串的长度范围[1, 100000]之间;

输出描述:

若str1是str2的关联子串,请返回子串在str2的起始位置;

若不是关联子串,则返回-1。

若str2中有多个str1的组合子串,请返回最小的起始位置。

示例 1:

abc efghicbaiii
5

示例2:

abc efghiccaiii
-1

2  解答

这道算法,我刚开始的时候我老想着 str1 的排列组合那么多,得到它所有的排列组合然后逐个判断是不是 str2 的子串,再从中选取一个最小的索引位置返回。但是所有的排列组合,那家伙字符串稍微长点那家伙量级岂不是很大貌似是 str1 长度的阶乘。所以我们换个角度去想,因为排列组合所以是任意的,但长度是固定的,我们是不是先分析下 str1 的组成比如是 a1b2c3d2 表示 a字符有1个、b字符2个、c字符3个、d字符2个,那么我们是不是在 str2 中每次取这样相等的长度,然后只要凑出这样的组成是不是就表示是关联子串了吧。我们用代码实现一下:

// 关联子串
public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    // 字符串1
    String str1 = "abc";
    // 字符串2
    String str2 = "efghiccaiii";

    // 默认返回结果
    int res = -1;
    int str1Len = str1.length();
    int str2Len = str2.length();
    // 边界判断
    if (str1Len > 0 && str1Len <= str2Len) {
        // 存储字符构成
        int[] arr = new int[26];
        // 先分析下 str1
        for (int i = 0; i < str1Len; i++) {
            int index = str1.charAt(i) - 'a';
            arr[index] += 1;
        }
        // str1 的组成
        StringBuilder str1Builder = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > 0) {
                str1Builder.append((char)('a' + i) + "" + arr[i]);
            }
        }
        // 从 str2 每次遍历 str1 的长度出来 看看它的组成
        for (int i = 0; i < str2Len - str1Len; i++) {
            // 重置
            for (int j = 0; j < arr.length; j++) {
                arr[j] = 0;
            }
            // 分析子串组成
            for (int j = i; j < i + str1Len; j++) {
                int index = str2.charAt(j) - 'a';
                arr[index] += 1;
            }
            StringBuilder subBuilder = new StringBuilder();
            for (int j = 0; j < arr.length; j++) {
                if (arr[j] > 0) {
                    subBuilder.append((char)('a' + j) + "" + arr[j]);
                }
            }
            // 判断是否组成跟 str1 的相等,相等直接返回并退出循环
            if (subBuilder.toString().equals(str1Builder.toString())) {
                res = i;
                break;
            }
        }
        // 打印结果
        System.out.println(res);
    }
}

这题挺好,又提供了一种思考的角度,与其大费周折的分析所有的排列组合,不如直接分析其组成,然后等长度的分析另一个字符串即可。

posted @ 2024-12-14 18:37  酷酷-  阅读(17)  评论(0编辑  收藏  举报