(B卷,200分)- 字符串划分(Java & JS & Python & C)

题目描述

给定一个小写字母组成的字符串 s,请找出字符串中两个不同位置的字符作为分割点,使得字符串分成三个连续子串且子串权重相等,注意子串不包含分割点。

若能找到满足条件的两个分割点,请输出这两个分割点在字符串中的位置下标,若不能找到满足条件的分割点请返回0,0。

子串权重计算方式为:子串所有字符的ASCII码数值之和。

输入描述

输入为一个字符串,字符串由a~z,26个小写字母组成,5 ≤ 字符串长度 ≤ 200。

输出描述

输出为两个分割点在字符串中的位置下标,以逗号分隔

备注

只考虑唯一解,不存在一个输入多种输出解的情况

用例

输入 acdbbbca
输出 2,5
说明 以位置2和5作为分割点,将字符串分割为ac,bb,ca三个子串,每一个的子串权重都为196,输出为:2,5
输入 abcabc
输出 0,0
说明 找不到符合条件的分割点,输出为:0,0

题目解析

本题数量级不大,可以考虑暴力求解。即定义两个指针i, j,去模拟两个分割点,其中 i < j,且 j – i > 1,因为被分割的子串至少有1个字母。

另外,为了避免重复求解某范围内的子串权重,我们可以使用前缀和,实现O(1)时间计算出任意区间内的子串权重。

关于前缀和知识,可以看:

JS算法源码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
  const s = await readline();
  const chars = [...s].map((c) => c.charCodeAt());
  const n = chars.length;

  // 前缀和
  const preSum = new Array(n + 1).fill(0);
  for (let i = 1; i <= n; i++) {
    preSum[i] = preSum[i - 1] + chars[i - 1];
  }

  // i,j是分割点
  for (let i = 1; i < n; i++) {
    // sum1 是 0 ~ i-1 范围的ASCII码之和
    const sum1 = preSum[i] - preSum[0];

    for (let j = i + 2; j < n; j++) {
      // sum2 是 i + 1 ~ j - 1 范围的ASCII码之和
      const sum2 = preSum[j] - preSum[i + 1];

      // 剪枝
      if (sum1 < sum2) break;

      if (sum1 == sum2) {
        // sum3 是 j + 1 ~ n - 1 范围的ASCII码之和
        const sum3 = preSum[n] - preSum[j + 1];

        if (sum2 == sum3) {
          return console.log(`${i},${j}`);
        }
      }
    }
  }

  console.log("0,0");
})();

Java算法源码

import java.util.Scanner;

public class Main {

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.println(getResult(sc.nextLine()));
  }

  public static String getResult(String s) {
    char[] chars = s.toCharArray();
    int n = chars.length;

    // 前缀和
    int[] preSum = new int[n + 1];
    for (int i = 1; i <= n; i++) {
      preSum[i] = preSum[i - 1] + chars[i - 1];
    }

    // i,j是分割点
    for (int i = 1; i < n; i++) {
      // sum1 是 0 ~ i-1 范围的ASCII码之和
      int sum1 = preSum[i] - preSum[0];
      for (int j = i + 2; j < n; j++) {
        // sum2 是 i + 1 ~ j - 1 范围的ASCII码之和
        int sum2 = preSum[j] - preSum[i + 1];

        // 剪枝
        if (sum1 < sum2) break;

        if (sum1 == sum2) {
          // sum3 是 j + 1 ~ n - 1 范围的ASCII码之和
          int sum3 = preSum[n] - preSum[j + 1];

          if (sum2 == sum3) {
            return i + "," + j;
          }
        }
      }
    }

    return "0,0";
  }
}

Python算法源码

# 输入获取
s = input()


# 算法入口
def getResult():
    chars = list(map(ord, s))
    n = len(chars)

    # 前缀和
    preSum = [0] * (n+1)
    for i in range(1, n + 1):
        preSum[i] = preSum[i - 1] + chars[i - 1]

    # i,j是分割点
    for i in range(1, n):
        # sum1 是 0 ~ i-1 范围的ASCII码之和
        sum1 = preSum[i] - preSum[0]

        for j in range(i + 2, n):
            # sum2 是 i + 1 ~ j - 1 范围的ASCII码之和
            sum2 = preSum[j] - preSum[i + 1]

            # 剪枝
            if sum1 < sum2:
                break

            if sum1 == sum2:
                # sum3 是 j + 1 ~ n - 1 范围的ASCII码之和
                sum3 = preSum[n] - preSum[j + 1]

                if sum2 == sum3:
                    return f"{i},{j}"

    return "0,0"


# 算法调用
print(getResult())

C算法源码

#include <stdio.h>

#define MAX_SIZE 200

int main()
{
char str[MAX_SIZE];
scanf("%s", str);

int n = strlen(str);

// 前缀和
int preSum[MAX_SIZE + 1] = {0};
for(int i=1; i<=n; i++) {
preSum[i] = preSum[i-1] + str[i-1];
}

// i,j是分割点
for(int i=1; i<n; i++) {
// sum1 是 0 ~ i-1 范围的ASCII码之和
int sum1 = preSum[i] - preSum[0];

for(int j=i+2; j<n; j++) {
// sum2 是 i + 1 ~ j - 1 范围的ASCII码之和
int sum2 = preSum[j] - preSum[i+1];

// 剪枝
if(sum1 < sum2) break;

if(sum1 == sum2) {
// sum3 是 j + 1 ~ n - 1 范围的ASCII码之和
int sum3 = preSum[n] - preSum[j+1];

if(sum2 == sum3) {
printf("%d,%d", i, j);
return 0;
}
}
}
}

printf("0,0");

return 0;
}

免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?