Substring with Concatenation of All Words

本文探讨了一种高效的字符串匹配算法,用于找出字符串中所有由指定单词列表构成的子串的起始索引,通过逐步优化实现从超时到高效解决方案的转变。

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

题目描述:

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) ins that is a concatenation of each word inwords exactly once and without any intervening characters.

For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]

You should return the indices: [0,9].
(order does not matter).

最笨的办法就是枚举出来所有的子集,然后再从S中得到相应的index、不出意外超时了。

public List findSubstring(String s, String[] words) {
	List list=new ArrayList();
	for (int i = 0; i < words.length; i++) {
		list.add(words[i]);
	}
	StringBuilder sb=new StringBuilder();
	List wordList=new ArrayList();
	List result=new ArrayList();
	getAllSubString(list, sb, wordList);
	for (int i = 0; i < wordList.size(); i++) {
		int index;
		if((index=s.indexOf(wordList.get(i)))!=-1){
			result.add(index);
		}
	}
	return result;
}

public void getAllSubString(List list,StringBuilder sb,List result){
	if(list.size()==0)
		result.add(sb.toString());
	for(int i=0;i newList=new ArrayList(list);
		newList.remove(list.get(i));
		getAllSubString(newList, newSb, result);
	}
}

后来用hashtable,创建map<string,integer>,int记录单词的个数,这样也超时了。此时的复杂度是O(m*n):

public List findSubstring(String s, String[] words) {
    int n=words.length;
    int len=words[0].length();
    Map map=new HashMap();
    List result=new ArrayList();
    for(int i=0;i0){
            map.put(str, map.get(str) - 1);  
           cnt++;  
           start += len;  
           if (start + len > s.length()) break; //注意越界  
           str = s.substring(start, start + len);
        }
        if (cnt == n) {  
            result.add(i);  
        } 
        if(cnt>0){
            map.clear();
            for(int j=0;j

后来参考了别人的做法,实在是巧妙。

public List findSubstring(String S, String[] L) {  
    List ret = new ArrayList();  
    int slen = S.length(), llen = L.length;  
    if (slen <= 0 || llen <= 0)  
        return ret;  
    int wlen = L[0].length();  

    // get the words' map  
    HashMap words = new HashMap();  
    for (String str : L) {  
        if (words.containsKey(str)) {  
            words.put(str, words.get(str) + 1);  
        } else {  
            words.put(str, 1);  
        }  
    }  

    for (int i = 0; i < wlen; ++i) {  
        int left = i, count = 0;  
        HashMap tmap = new HashMap();  

        for (int j = i; j <= slen - wlen; j += wlen) {  
            String str = S.substring(j, j + wlen);  

            if (words.containsKey(str)) {  
                if (tmap.containsKey(str)) {  
                    tmap.put(str, tmap.get(str) + 1);  
                } else {  
                    tmap.put(str, 1);  
                }  

                if (tmap.get(str) <= words.get(str)) {  
                    count++;  
                } else {  
                    // too many words, push the 'left' forward  
                    while (tmap.get(str) > words.get(str)) {  
                        String tmps = S.substring(left, left + wlen);  
                        tmap.put(tmps, tmap.get(tmps) - 1);  
                        if (tmap.get(tmps) < words.get(tmps)) {  
                            // if affect the count  
                            count--;  
                        }  
                        left += wlen;  
                    }  
                }  

                // get the answer  
                if (count == llen) {  
                    ret.add(left);  
                    // it's better to push forward once  
                    String tmps = S.substring(left, left + wlen);  
                    tmap.put(tmps, tmap.get(tmps) - 1);  
                    count--;  
                    left += wlen;  
                }  
            } else {  
                // not any match word  
                tmap.clear();  
                count = 0;  
                left = j + wlen;  
            }  
        }  
    }  
    return ret;  
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值