Substring with Concatenation of All Words 找子串组合的下标 @LeetCode

本文探讨了一种使用KMP算法优化解决子串拼接问题的方法,通过对比原有暴力法,展示了如何提高算法效率并找到优化点。

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

思路:

把所有的子串存入Hashtable,对原字符串进行O(n2)的搜索,看能不能用完Hashtable所有的字串


本题用了不是很好的暴力法压线通过,下次改成用KMP的方法重写一遍。现在还太弱了,不会KMP。。。T^T

还遇到了很奇怪的问题,在代码中注释体现。


package Level3;

import java.util.ArrayList;
import java.util.Hashtable;

/**
 * Substring with Concatenation of All Words
 * You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters.

For example, given:
S: "barfoothefoobarman"
L: ["foo", "bar"]

You should return the indices: [0,9].
(order does not matter).
 */
public class S30 {

	public static void main(String[] args) {
		String S = "barfoothefoobarman";
		String[] L = {"foo", "bar"};
//		String S = "a";
//		String[] L = {"a"};
		
		System.out.println(findSubstring(S, L));
	}
	
	// 用暴力法压线通过,未来应该用类似KMP的方法降低复杂度!
	public static ArrayList<Integer> findSubstring(String S, String[] L) {
		
		ArrayList<Integer> ret = new ArrayList<Integer>();
		
        Hashtable<String, Integer> ht = new Hashtable<String, Integer>();
        // 把L中的string全部添加入hashtable
        for (String str : L) {
			if(ht.containsKey(str)){
				ht.put(str, ht.get(str)+1);
			}else{
				ht.put(str, 1);
			}
		}
        
        int wordLen = L[0].length();
        int numberOfWords = L.length;
        
        // Brute force法比较
        for(int i=0; i<=S.length()-numberOfWords*wordLen; i++){
        	// 每次要基于原hashtable新建一个hashtable
        	Hashtable<String, Integer> table = new Hashtable<String, Integer>(ht);
        	int cnt = 0;
        	
        	// j每次都重复地做相同的工作
        	for(int j=i; j<=i+numberOfWords*wordLen-wordLen; j+=wordLen){
        		String substr = S.substring(j, j+wordLen);
            	if(table.containsKey(substr)){
            		// 如果只用这一句会TLE
//            		table.put(substr, table.get(substr)-1);
            		
            		// 改成这样就能压线AC
            		int times = table.get(substr);
                    if(times == 1) table.remove(substr);
                    else table.put(substr, times - 1);
                    
            		cnt++;
            	}else{
            		break;
            	}
        	}
        	
        	if(cnt == numberOfWords){
        		ret.add(i);
        	}
        }
        
        return ret;
    }

}


找到压线通过的方法:http://www.cnblogs.com/lichen782/archive/2013/07/06/leetcode_SubstringwithConcatenationofAllWords.html

KMP的初步认识: http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

一个基于KMP的解决方法:http://n00tc0d3r.blogspot.com/2013/06/substring-with-concatenation-of-all.html



import java.util.*;

public class Solution {
    public List<Integer> findSubstring(String S, String[] L) {
        List<Integer> ret = new ArrayList<Integer>();
        int m = L.length;
        if(m == 0) {
            return ret;
        }
        int n = L[0].length();
        Hashtable<String, Integer> ht = new Hashtable<String, Integer>();
        for(String word : L) {
            Integer cnt = ht.get(word);
            if(cnt == null) {
                ht.put(word, 1);
            } else {
                ht.put(word, cnt+1);
            }
        }
        
        for(int i=0; i<=S.length()-n*m; i++) {
            Hashtable<String, Integer> tmp = new Hashtable<String, Integer>();
            int j = 0;
            for(j=0; j<m; j++) {
                int k = i + j*n;    // n-characters interval
                String substr = S.substring(k, k+n);
                Integer cntInHt = ht.get(substr);       // check if substr in Hashtable
                Integer cntInTmp = tmp.get(substr);     // check if substr in temporary Ht
                // must be in the original Hashtable and found cnts of character should be less than all available characters
                if(cntInHt != null && (cntInTmp == null || cntInTmp < cntInHt)) {
                    if(cntInTmp == null) {
                        tmp.put(substr, 1);
                    } else {
                        tmp.put(substr, cntInTmp+1);
                    }
                } else {
                    break;
                }
            }
            if(j == m) {        // found all words in L
                ret.add(i);
            }
         }
        
        return ret;
    }
}




资源下载链接为: https://pan.quark.cn/s/d9ef5828b597 当使用 MySQL 5.5 版本的用户在 Windows 系统下忘记 root 账户密码时,可采用以下两种方法解决。 方法一:命令行操作 先关闭 MySQL 服务,通过命令提示符输入“net stop mysql”来实现。 接着用“mysqld --skip-grant-tables”命令启动 MySQL 服务,这样启动时不会加载权限表,能绕过密码验证直接登录。 打开新的命令提示符窗口,进入 MySQL 的 bin 目录,执行“mysql”命令启动客户端程序,无需密码即可登录。 登录后,输入“show databases;”查看所有数据库。 使用“use mysql;”切换到 mysql 数据库。 执行“update users set password=PASSWORD(新密码) where user=root;”更新 root 用户密码,其中“新密码”是自己想设置的密码。 输入“flush privileges;”重新加载权限表。 输入“quit”退出客户端,再通过“net start mysql”重启 MySQL 服务。 方法二:通过默认账户登录 在 Windows 命令提示符中停止 MySQL 服务。 直接运行“mysql -u root”启动 MySQL 客户端,可能需以管理员身份运行命令提示符,或使用有默认无密码登录权限的用户。 在客户端执行“use mysql;”进入 mysql 数据库。 再执行“update users set password=PASSWORD(新密码) where user=root;”更新密码。 执行“flush privileges;”重新加载权限表。 输入“quit”退出客户端,重启 MySQL 服务。 操作时要注意:Windows 下路径和
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值