LeetCode:求拆分字符串所得最大个数

这篇博客探讨了一种算法问题,即给定一个字符串,如何拆分它以获得最大数量的唯一子字符串。算法通过深度优先搜索实现,使用哈希集合来检查子字符串的唯一性。在Go和C++中分别给出了代码实现,通过对字符串的每个可能拆分点进行检查,并在不引入重复子串的情况下进行拆分,从而达到最大化唯一子串的目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
给你一个字符串s,请你拆分该字符串,并返回拆分后唯一子字符串的最大数目.字符串s拆分
后可以得到若干 非空子字符串,这些子字符串连接后应当能够还原为原字符串.但是拆分出来
的每个子字符串都必须是唯一的.
注意:子字符串是字符串中的一个连续字符序列.

示例 1:
Input:s="ababccc"
Output:5
解释:一种最大拆分方法为['a','b','ab','c','cc'].像['a','b','a','b','c','cc']
这样拆分不满足题目要求,因为其中的'a'和'b'都出现了不止一次.

示例 2:
Input:s="aba"
Output:2
解释:一种最大拆分方法为['a','ba']

示例 3:
Input:s="aa"
Output:1
解释:无法进一步拆分字符串.
 

提示:
(1)1<=s.length<=16
(2)s仅包含小写英文字母

解题思路:
对于长度为n的字符串,有n−1个拆分点.从左到右遍历字符串,对于每个拆分点,如果在
此拆分之后,新得到的一个非空子字符串,即拆分点左侧的最后一个被拆分出的非空子字
符串,与之前拆分出的非空子字符串都不相同,则当前的拆分点可以进行拆分,然后继续
对剩下的部分(即拆分点右侧的部分)进行拆分.
(1)回溯(深度优先遍历);
(2)使用一个哈希验证是否已有重复子串,这里使用set容器,insert的返回值是pair对,第一个
    是当前的迭代器,第二个是bool类型;
(3)判断剩余字符长度和已有答案,进行剪枝;
*/

Go语言实现

package main

import "fmt"

func maxUniqueSplit(s string) int{
	words:=map[string]bool{}
	count:=0
	var dfs func(string)
	dfs=func (s string){
		if len(words)+len(s)<count{
			return
		}
		if len(s)==0{
			count=max(count,len(words))
			return
		}
		for i:=0;i<len(s);i++{
			cur:=s[:i + 1]
			if _,ok:=words[cur];!ok {
				words[cur]=true
				dfs(s[i+1:])
				delete(words,cur)
			}
		}
	}
	dfs(s)
	return count
}

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

func main(){
	fmt.Println("拆分字符串求最大个数")
	s:="wwwhhtp"
	fmt.Println(maxUniqueSplit(s))
}

C++语言实现

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;


class Solution{
public:
    Solution(string& _s):S(_s),count(0){}
    void dfs(string& s,int x,int n){
        if(x==n){
            bool flag=true;
            hash.clear();
            for(string& w:words){
                if(hash.insert(w).second==false)
                   flag=false;
            }
            if(flag)
               count=max(count,(int)words.size());
        }else{
            string cur="";
            for(int i=x;i<n;i++){
                cur+=s[i];/*单个字符*/
                words.push_back(cur);
                dfs(s,i+1,n);
                words.pop_back();
            }
        }
    }
    int maxUniqueSplit(){
        dfs(S,0,S.size());
        return count;
    }  
private:
    string S;
    set<string> hash;
    vector<string> words;
    int count;
};

int main(int argc,char* argv[]){
    string S="wwwzfvedwfvhsww";
    Solution solu(S);
    cout<<solu.maxUniqueSplit()<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上的追梦人

您的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值