目录
题目部分
题目 | 字符串比较 |
难度 | 难 |
题目说明 | 给定字符串A、B和正整数V,A的长度与B的长度相等,请计算A中满足如下条件的最大连续子串的长度: 1、该连续子串在A和B中的位置和长度均相同。 2、该连续子串|A[i]–B[i]|之和小于等于V。其中|A[i]–B[i]|表示两个字母ASCII码之差的绝对值。 |
输入描述 | 输入为三行: 第一行为字符串A,仅包含小写字符,1<=A.length<=1000。 第二行为字符串B,仅包含小写字符,1<=B.length<=1000。 第三行为正整数V,0<=V<=10000。 |
输出描述 | 字符串最大连续子串的长度,要求该子串|A[i]–B[i]|之和小于等于V。 |
补充说明 | 无 |
------------------------------------------------------ | |
示例 | |
示例1 | |
输入 | xxcdefg cdefghi 5 |
输出 | 2 |
说明 | 字符串 A 为 xxcdefg,字符串 B 为 cdefghi,V = 5。 它的最大连续子串可以是 cd -> ef、de -> fg、ef -> gh、fg -> hi,所以最大连续子串是 2。 |
解读与分析
题目解读:
两个字符串A、B的长度相等,设下标为 i 的字符 A[i] 与 B[i] 对应的 ASCII 码的绝对值为 diffAbs[i]。diffAbs 中连续的 n 个元素之和小于或等于 V,求 n 的最大值。
分析与思路:
此题虽然难度虽然是“难”,实际很简单。
先遍历字符串A、B,依次计算每一个字符 A[i]、B[i] 的 ASCII 码的绝对值之差,存放到整型数组 diffAbs 中。
接着遍历 diffAbs,从第一个元素 diffAbs[0] 开始寻找连续元素之和小于或等于 V 的区块,设区块的左下标为 leftIndex,右下标为 rightIndex。初始值 leftIndex、rightIndex 均为 0,当区块中元素之和大于 V 时,leftIndex 向右移动(注意要保证 rightIndex >= leftIndex);当和小于 rightIndex 时,rightIndex 往右移动。直到 rightIndex 到达最后一个元素。在滑动过程中,( rightIndex - leftIndex + 1 ) 的最大值即为最大的连续个数。
需要遍历两次,其中第一次为遍历字符串A、B,第二次遍历数组 diffAbs。时间复杂度和空间复杂度均为 O(n)。
此题和往期的题《华为OD机考算法题:补种未成活胡杨》《华为OD机考算法题:根据某条件聚类最少交换次数》《华为OD机考算法题:区块链文件转储系统》比较类似。
代码实现
Java代码
import java.util.Scanner;
/**
* 字符串比较
* @since 2023.10.09
* @version 0.1
* @author Frank
*
*/
public class StringComparation {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String strA = sc.nextLine();
String strB = sc.nextLine();
String strV = sc.nextLine();
int v = Integer.parseInt( strV );
processStringComparation( strA, strB, v );
}
}
private static void processStringComparation( String strA, String strB, int v )
{
int[] diffAbs = new int[ strA.length() ];
for( int i = 0; i < diffAbs.length; i ++ )
{
int eachDiffAbs = Math.abs( strA.charAt( i ) - strB.charAt( i ) );
diffAbs[i] = eachDiffAbs;
}
int leftIndex = 0;
int rightIndex = 0;
int maxCount = 0;
int curSum = diffAbs[0];
while( rightIndex <= diffAbs.length - 1 )
{
if( curSum > v )
{
if( leftIndex >= diffAbs.length - 1 )
{
break;
}
curSum -= diffAbs[ leftIndex ];
leftIndex ++;
if( rightIndex < leftIndex )
{
rightIndex = leftIndex;
curSum += diffAbs[ rightIndex ];
}
continue;
}
// curSum <= v
if( rightIndex - leftIndex + 1 >= maxCount )
{
maxCount = rightIndex - leftIndex + 1;
}
if( rightIndex >= diffAbs.length - 1 )
{
break;
}
rightIndex ++;
curSum += diffAbs[ rightIndex ];
}
System.out.println( maxCount );
}
}
JavaScript代码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function() {
while (line = await readline()) {
var strA = line;
var strB = await readline();
var strV = await readline();
var v = parseInt(strV);
processStringComparation(strA, strB, v);
}
}();
function processStringComparation(strA, strB, v) {
var diffAbs = new Array();
for (var i = 0; i < strA.length; i++) {
var eachDiffAbs = Math.abs(strA.charCodeAt(i) - strB.charCodeAt(i));
diffAbs[i] = eachDiffAbs;
}
var leftIndex = 0;
var rightIndex = 0;
var maxCount = 0;
var curSum = diffAbs[0];
while (rightIndex <= diffAbs.length - 1) {
if (curSum > v) {
if (leftIndex >= diffAbs.length - 1) {
break;
}
curSum -= diffAbs[leftIndex];
leftIndex++;
if (rightIndex < leftIndex) {
rightIndex = leftIndex;
curSum += diffAbs[rightIndex];
}
continue;
}
// curSum <= v
if (rightIndex - leftIndex + 1 >= maxCount) {
maxCount = rightIndex - leftIndex + 1;
}
if (rightIndex >= diffAbs.length - 1) {
break;
}
rightIndex++;
curSum += diffAbs[rightIndex];
}
console.log(maxCount);
}
(完)