首页 > 其他分享 >2024-05-04:用go语言,给定一个起始索引为0的字符串s和一个整数k。 要进行分割操作,直到字符串s为空: 选择s的最长前缀,该前缀最多包含k个不同字符; 删除该前缀,递增分割计数。如果有剩余

2024-05-04:用go语言,给定一个起始索引为0的字符串s和一个整数k。 要进行分割操作,直到字符串s为空: 选择s的最长前缀,该前缀最多包含k个不同字符; 删除该前缀,递增分割计数。如果有剩余

时间:2024-05-04 15:23:41浏览次数:20  
标签:字符 分割 前缀 int changed mask dfs 字符串

2024-05-04:用go语言,给定一个起始索引为0的字符串s和一个整数k。

要进行分割操作,直到字符串s为空:

选择s的最长前缀,该前缀最多包含k个不同字符;

删除该前缀,递增分割计数。如果有剩余字符,它们保持原来的顺序。

在操作之前,可以修改字符串s中的一个字符为另一个小写英文字母。

在最佳情况下修改至多一次字符后,返回操作结束时得到的最大分割数量。

输入:s = "accca", k = 2。

输出:3。

答案2024-05-04:

chatgpt

题目来自leetcode3003。

大体步骤如下:

1.创建一个递归函数dfs,用于计算分割得到的最大数量。

2.函数中,首先检查是否到达字符串末尾,若是则返回 1(表示完成一个分割)。

3.使用memo记录中间结果,加快计算速度。

4.对于当前处理的字符s[i],如果不将其作为新的分割点,继续处理下一个字符。

5.如果将s[i]作为新的分割点,并且新的字符数量不超过k,则继续向后处理。

6.如果未修改过字符,则尝试修改s[i]为其他26个小写字母,然后继续考虑分割带来的最大数量。

7.在每一步中,根据是否修改过字符,记录当前的最大分割数量。

8.最终返回得到的最大分割数量。

总的时间复杂度为 $O(n \cdot 2{26})$,其中$n$为字符串长度,$2$表示尝试修改字符的可能性数目。

总的额外空间复杂度为$O(n \cdot 2^{26})$,主要由memo中间结果记录所占用的空间引起。

Go完整代码如下:

package main

import (
	"fmt"
	"math/bits"
)

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func maxPartitionsAfterOperations(s string, k int) int {
	n := len(s)
	type args struct {
		i, mask int
		changed bool
	}
	memo := map[args]int{}
	var dfs func(int, int, bool) int
	dfs = func(i, mask int, changed bool) (res int) {
		if i == n {
			return 1
		}

		a := args{i, mask, changed}
		if v, ok := memo[a]; ok { // 之前计算过
			return v
		}

		// 不改 s[i]
		bit := 1 << (s[i] - 'a')
		newMask := mask | bit
		if bits.OnesCount(uint(newMask)) > k {
			// 分割出一个子串,这个子串的最后一个字母在 i-1
			// s[i] 作为下一段的第一个字母,也就是 bit 作为下一段的 mask 的初始值
			res = dfs(i+1, bit, changed) + 1
		} else { // 不分割
			res = dfs(i+1, newMask, changed)
		}

		if !changed {
			// 枚举把 s[i] 改成 a,b,c,...,z
			for j := 0; j < 26; j++ {
				newMask := mask | 1<<j
				if bits.OnesCount(uint(newMask)) > k {
					// 分割出一个子串,这个子串的最后一个字母在 i-1
					// j 作为下一段的第一个字母,也就是 1<<j 作为下一段的 mask 的初始值
					res = max(res, dfs(i+1, 1<<j, true)+1)
				} else { // 不分割
					res = max(res, dfs(i+1, newMask, true))
				}
			}
		}

		memo[a] = res // 记忆化
		return res
	}
	return dfs(0, 0, false)
}

func main() {
	s := "accca"
	k := 2
	result := maxPartitionsAfterOperations(s, k)
	fmt.Println(result)
}

在这里插入图片描述

Python完整代码如下:

# -*-coding:utf-8-*-

def max_partitions_after_operations(s, k):
    n = len(s)
    memo = {}

    def dfs(i, mask, changed):
        if i == n:
            return 1

        a = (i, mask, changed)
        if a in memo:
            return memo[a]

        res = 0
        bit = 1 << (ord(s[i]) - ord('a'))
        new_mask = mask | bit

        if bin(new_mask).count('1') > k:
            res = dfs(i + 1, bit, changed) + 1
        else:
            res = dfs(i + 1, new_mask, changed)

        if not changed:
            for j in range(26):
                new_mask = mask | 1 << j
                if bin(new_mask).count('1') > k:
                    res = max(res, dfs(i + 1, 1 << j, True) + 1)
                else:
                    res = max(res, dfs(i + 1, new_mask, True))

        memo[a] = res
        return res

    return dfs(0, 0, False)

s = "accca"
k = 2
result = max_partitions_after_operations(s, k)
print(result)

在这里插入图片描述

标签:字符,分割,前缀,int,changed,mask,dfs,字符串
From: https://www.cnblogs.com/moonfdd/p/18172347

相关文章

  • 无符号整数转二进制字符串逆序输出
    无符号整数转二进制逆序在C语言中,要实现一个函数来传入一个八位无符号整数,并返回其二进制倒序的字符串,你可以使用以下步骤:分配足够的堆空间来存储倒序后的二进制字符串。利用位运算符获取当成8位无符号整数的二进制数可以从高位往遍历也可以从低位往高位遍历从高遍......
  • python教程3.1:数据类型:字符串+列表list
    一、字符串字符串是⼀个有序的字符的集合,⽤于在计算机⾥存储和表示⽂本信息 常用操作二、列表list[]内以逗号分隔,按照索引,存放各种数据类型,每个位置代表⼀个元素特征 1、增加操作   追加,数据会追加到尾部 2、删除操作3、修改操作 4、查找操作 如果......
  • 字符串基础(hash,KMP,AC自动机,trie)
    trie树trie树,又叫字典树,就是把字符串的每个字母看做树上的一个节点,若干个字符串组成了一棵trie树。最一般的trie树好像只能搜索字符串,重点是01trie和可持久化trie树和用trie树来建ac自动机(详见AC自动机)。这里着重介绍一下01trie01trie,就是节点代表了数上的二进制位上的数。......
  • 高效遍历:C++中分隔字符串单词的3种方法详解与实例
     概述:在C++中,遍历由空格分隔的字符串的单词有多种方法,包括使用`std::istringstream`、手动遍历字符和正则表达式。其中,`std::istringstream`是简单高效的选择,通过流提取单词。手动遍历字符较为繁琐,正则表达式方法更灵活但可能有性能开销。根据实际需求选择方法,本文提供了清晰......
  • cpp字符串相关
    字符串相关文章参考:[详解-字符串]C++必知必会字符串-string常用各种操作解析-知乎(zhihu.com)C++字符串(string)常用操作总结-知乎(zhihu.com)c++读取字符串和字符的6种函数_c++获取字符串的每个字符-CSDN博客头文件#include<string>定义字符串stringstr;初始......
  • 枚举范围内的字符串
    我写的:publicintVowelStrings(string[]words,intleft,intright){strings="aeiou";intk=0;for(inti=left;i<=right;i++){intx=0,y=0;stringword=words[i];intwordLong......
  • 50种常见的图像分割技术
    边缘检测分割:通过检测图像中的边缘来分割图像,例如Canny边缘检测算子。区域生长分割:从一组种子点开始,逐步增长区域,直到满足一定的相似性条件。区域分裂与合并分割:通过分裂和合并区域来分割图像,例如基于区域的分裂合并算法。基于阈值的分割:除了简单的全局阈值分割,还有局......
  • C语言程序设计——字符串典型题练习
    1、计算一个字符串中最大的重复子串的字符的数量/********************************************************************* name : CalSubStrMaxCnt* function:计算一个字符串中最大的重复子串的字符的数量* argument:* @str:需要查找的字符串的地址* * ret......
  • 使用g开头的数组字符串的解析
    在做ofd的文件解析的时候,会遇到带有这种描述的数组"g22.03g31.20.2"。这个字符串通过空格进行分割得到一个["g",2,2.0,3,"g",3,1.2,0.2]这样的数组数据。这个是以g表示一个数组的开头,包含了2个元素,每个元素都是2.0的数组。整个字符串翻译成一个完整的数组就是这样......
  • Java中“==”与“equals”在字符串比较中的应用与分析
    packagecom.aiit.helloworld;publicclassHelloWorld{ publicstaticvoidmain(Stringargs[]){ Strings1="a"+"b"; Strings2=newString(s1); if(s1==s2)//false System.out.println("doit~~~"); if(s1.equals(s......