LeetCode 30 Substring with Concatenation of All Words--In Java

本文介绍了一种使用哈希映射和哈希集进行优化的子串匹配算法,该算法能够高效地找出字符串中由给定单词数组组成的全部子串起始位置。

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

主要想法为:

建立一个hashmap<String ,int>保存所有words中的单词,记录下它们各自出现的次数。然后外层循环从文本串中依次取下长度等于words中单词拼接后长度的子串,程序中为变量ps。内层循环从ps中每次截取一个单词,这时我们拷贝一份先前的hashmap,这个单词出现一次,就在hashmap的指定键值处减一,如果发生有一个值被减到小于0,则是一次失败的匹配,内层循环退出。同时,如果根本没有找到这个从ps里截到的单词,同样查找失败,内层循环退出。

当然到这里还是不够的,如果文本串中大量出现了words中的单词,这个方法的效率就会很低。这里做了优化:建立一个hashset保存着已扫描的所有失败案例,当新的ps在这个失败案例集中时,直接判定失败。

public List<Integer> findSubstring(String s, String[] words) {
        int N = s.length();
        int M = words.length;
        HashMap ct = new HashMap();
        HashSet<String> hs = new HashSet();
        List<Integer> result = new LinkedList();
        for(int i=0;i<M;i++){
        	if(ct.containsKey(words[i])){
        		int c = (int) ct.get(words[i]);
        		ct.put(words[i], ++c);
        	}else{
        		ct.put(words[i], 1);
        	}
        }
        
        int wlen = words[0].length();
        int getj = 0;
        for(int i=0;i<N-wlen*M+1;i++){
        	String ps = s.substring(i,i+wlen*M);
        	
        	if(hs.contains(ps)){
        		continue;
        	}
        	
        	HashMap nc = (HashMap) ct.clone();
        	getj=0;
        	for(int j=0;j<wlen*M-wlen+1;j=j+wlen,getj=j){
        		
        		String tryfind = ps.substring(j,j+wlen);
        		if(nc.containsKey(tryfind)==false){
        			hs.add(ps);
        			break;
        		}else if((int) nc.get(tryfind)>0){
        			int c = (int) nc.get(tryfind);
        			c--;
        			nc.put(tryfind, c);
        		}else{
        			hs.add(ps);
        			break;
        		}
        	}
        	
        	if(getj>=wlen*M-wlen+1)
        		result.add(i);
        }
        
        
        return result;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值