106.串联所有单词的字串

本文探讨了如何使用哈希查找和滑动窗口算法解决给定字符串中由一组固定长度单词串联的子串查找问题。通过实例演示,展示了如何统计子串中单词出现次数并与给定单词列表对比,找到满足条件的子串起始位置。

一、题目描述

给定一个字符串 s 和一些长度相同的单词 words 。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符 ,但不需要考虑 words 中单词串联的顺序。
在这里插入图片描述
在这里插入图片描述

二、解题思路

方案一:使用哈希查找,具体看代码。

方案二:滑动窗口

以示例一为例,因为words中的单词长度是3,所以每3个字母是一组
在这里插入图片描述
第一步:前三个是一组,然后和words中的单词比较,发现bar出现了一次,然后right继续向后找,发现foo也出现了一次,这时words中的每个单词都出现了,且次数也符合,更新当前结果集res=0
在这里插入图片描述
在这里插入图片描述
第二步:right继续向后遍历,这时the并不是words中的单词,就要缩小窗口,left向后移动到the后面重新开始:
在这里插入图片描述
重复第一第二步,当满足words中的单词和其次数都在窗口中出现时,则更新res

三、代码演示

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        //声明一个结果集
        Map<String, Integer> map = new HashMap<>();

        //统计word中每个单词出现的次数
        for (String word : words){
            //getOrDefault表示当前有word值就获取key对应的value,没有返回默认值0
            map.put(word, map.getOrDefault(word, 0)+1);
        }

        //一个单词的长度,题目说了words中单词长度相同
        int oneWordLen = words[0].length();
        //单词个数
        int wordNum = words.length;
        //所有单词总长度
        int totalLen = oneWordLen * wordNum;

        List<Integer> res = new ArrayList<>();
        for (int i=0; i<s.length()-totalLen+1; i++){
            //拿到等于所有单词长度之和的字串
            String subStr = s.substring(i, i+totalLen);
            //统计子串中单词出现的次数
            Map<String, Integer> tmpMap = new HashMap<>();
            for (int j=0; j<totalLen; j+=oneWordLen){
                String oneWord = subStr.substring(j, j+oneWordLen);
                tmpMap.put(oneWord, tmpMap.getOrDefault(oneWord, 0)+1);
            }

            //如果单词出现的次数和原始words中单词出现的此时相同,则符合条件
            if (map.equals(tmpMap)){
                res.add(i);
            }
        }
         return res;
    }
}

时间复杂度:O(n^2)

滑动窗口代码:

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        //声明一个结果集
        Map<String, Integer> map = new HashMap<>();

        //统计word中每个单词出现的次数
        for (String word : words){
            //getOrDefault表示当前有word值就获取key对应的value,没有返回默认值0
            map.put(word, map.getOrDefault(word, 0)+1);
        }

        //一个单词的长度,题目说了words中单词长度相同
        int oneWordLen = words[0].length();
        //单词个数
        int wordNum = words.length;
        //所有单词总长度
        int totalLen = oneWordLen * wordNum;
        //声明一个结果集
        List<Integer> res = new ArrayList<>();
        for (int i=0; i<oneWordLen; i++){
            //声明一个指针
            int left=i, right=i;
            //使用一个变量来存储匹配单词的个数
            int matchedWords = 0;
            Map<String, Integer> windowMap = new HashMap<>();
            while (right<=s.length()-oneWordLen){
                //获取到当前单词
                String currWord = s.substring(right, right+oneWordLen);
                //将当前单词加到窗口里面
                windowMap.put(currWord, windowMap.getOrDefault(currWord,0)+1);
                matchedWords++;
                //如果当前窗口里面单词出现的次数大于words里面单词出现的次数,则缩减窗口
                while (windowMap.getOrDefault(currWord,0)>map.getOrDefault(currWord,0)){
                    String leftWord = s.substring(left,left+oneWordLen);
                    windowMap.put(leftWord, windowMap.getOrDefault(leftWord,0)-1);
                    left += oneWordLen;
                    matchedWords--;
                }
                if (matchedWords == wordNum){
                    res.add(left);
                }
                right += oneWordLen;
            }
        }
        return res;
    }
}

<think> 我们正在讨论在ASP.NET MVC框架中使用`@Url.Action`方法拼接字符串的场景。根据引用内容,我们注意到拼接URL时需要考虑特殊字符的处理(引用[2][4])以及不同上下文中的转义要求(引用[4])。虽然引用中没有直接提到`@Url.Action`,但我们可以借鉴这些原则。 `@Url.Action`是ASP.NET MVC中用于生成URL的Razor语法方法。它通常用于视图中生成指向控制器操作的URL。当需要拼接额外参数(如查询字符串)时,我们可以传递一个匿名对象或使用`string.Format`等方法构建查询字符串部分。 ### 使用方法 1. **基本用法**:生成不带参数的URL ```csharp <a href="@Url.Action("Index", "Home")">主页</a> ``` 2. **带路由参数**:通过匿名对象传递 ```csharp <a href="@Url.Action("Details", "Product", new { id = 123 })">产品详情</a> ``` 3. **拼接查询字符串**:如果需要在生成的URL后追加自定义查询字符串,建议使用`QueryString`属性或直接拼接: ```csharp @{ string baseUrl = Url.Action("Search", "Product"); string fullUrl = $"{baseUrl}?name=手机&price=1000-2000"; } <a href="@fullUrl">搜索手机</a> ``` ### 注意事项 - **特殊字符处理**:直接拼接字符串时,若包含中文或特殊字符(如`&`, `=`等),需要手动进行URL编码(引用[2][3])。ASP.NET MVC的`Url.Action`会自动编码路由参数,但手动拼接的查询字符串部分需自行处理: ```csharp @{ string productName = "C#教程"; string encodedName = HttpUtility.UrlEncode(productName); // 使用System.Web命名空间 string fullUrl = $"{Url.Action("Search")}?keyword={encodedName}"; } ``` - **避免XSS漏洞**:动态生成URL时,确保用户输入内容经过编码(引用[4])。切勿直接拼接未经验证的用户输入。 ### 示例 #### 场景:生成带多个查询参数的URL ```csharp @{ // 假设需要传递分类ID和排序方式 int categoryId = 5; string sortBy = "price_desc"; string baseUrl = Url.Action("List", "Product"); string query = $"category={categoryId}&sort={sortBy}"; string fullUrl = $"{baseUrl}?{query}"; } <a href="@fullUrl">价格从高到低</a> ``` #### 替代方案:使用匿名对象(推荐) 更安全的方式是利用`Url.Action`直接生成查询字符串: ```csharp @Url.Action("List", "Product", new { category = 5, sort = "price_desc" }) ``` 此方法会自动处理参数编码问题。 ### 总结 - 优先使用`Url.Action`的匿名对象参数传递查询条件,避免手动拼接。 - 必须手动拼接时,务必对每个参数值调用`HttpUtility.UrlEncode`。 - 在JavaScript中拼接URL同理(引用[2][5]),但Razor视图应尽量利用框架提供的URL生成方法。 §§相关问题§§ 1. 如何防止URL拼接中的XSS攻击? 2. ASP.NET Core中的URL生成方法与MVC 5有何不同? 3. 除了`Url.Action`,还有哪些生成URL的Razor语法? </think> ### `@Url.Action` 拼接字符串的使用方法与示例 在 ASP.NET MVC 中,`@Url.Action` 是 Razor 视图引擎提供的 URL 生成助手,用于动态生成指向控制器操作的 URL。拼接字符串时需注意**参数传递**、**特殊字符处理**和**安全性**(参考引用[2][4])。以下是具体方法和示例: --- #### **1. 基础语法** ```csharp @Url.Action("ActionName", "ControllerName", new { 参数 }) ``` - **`ActionName`**:目标操作方法名 - **`ControllerName`**:目标控制器名(可省略,默认为当前控制器) - **`参数`**:通过匿名对象传递路由值或查询字符串 --- #### **2. 拼接字符串的三种方式** ##### (1) **直接拼接查询参数** 通过匿名对象传递参数,自动生成 `?key=value` 格式: ```csharp @{ string id = "user123"; string role = "admin"; } <a href="@Url.Action("Profile", "User", new { userId = id, userRole = role })"> 用户详情 </a> ``` 生成结果: `/User/Profile?userId=user123&userRole=admin` > ✅ 推荐:自动处理 URL 编码,避免特殊字符问题(参考引用[2][3])。 --- ##### (2) **手动拼接路径片段** 使用 `+` 或 `string.Format` 拼接动态部分: ```csharp @{ string segment = "orders"; string url = Url.Action("Index", "User") + "/" + segment; } <a href="@url">查看订单</a> ``` 生成结果: `/User/Index/orders` > ⚠️ 需自行处理特殊字符(如空格、中文),否则可能出错(参考引用[4])。 --- ##### (3) **混合拼接(路径+查询参数)** 结合路由参数和查询字符串: ```csharp @{ string category = "books"; int page = 2; } <a href="@Url.Action("List", "Product", new { category }) + "?page=" + page"> 分页列表 </a> ``` 生成结果: `/Product/List/books?page=2` --- #### **3. 关键注意事项** 1. **URL 编码** 手动拼接时需显式编码特殊字符(参考引用[2][4]): ```csharp @using System.Web @{ string keyword = "C# & .NET"; string encodedKeyword = HttpUtility.UrlEncode(keyword); // 输出:C%23+%26+.NET string url = Url.Action("Search") + "?q=" + encodedKeyword; } ``` 2. **避免 XSS 漏洞** 动态参数来自用户输入时,必须编码以防止注入攻击(参考引用[4]): ```csharp // 错误:直接拼接未过滤的用户输入 string unsafeUrl = "/Download?file=" + userInput; // 正确:使用 UrlEncode string safeUrl = "/Download?file=" + HttpUtility.UrlEncode(userInput); ``` 3. **路由配置匹配** 拼接的路径需与 `RouteConfig` 中定义的路由模板一致,否则返回 404: ```csharp // RouteConfig.cs 定义 routes.MapRoute("Custom", "{controller}/{action}/{customSegment}"); // 视图中需匹配 customSegment @Url.Action("Index", "Home", new { customSegment = "value" }) ``` --- #### **4. 完整示例场景** ```html @{ // 动态参数 string productId = "p-1001"; string color = "blue+red"; // 含特殊字符 string encodedColor = HttpUtility.UrlEncode(color); // 编码后:blue%2bred } <!-- 生成商品详情页链接 --> <a href="@Url.Action("Detail", "Product", new { id = productId }) + "?color=" + encodedColor"> 蓝色与红色商品 </a> ``` 生成结果: `/Product/Detail/p-1001?color=blue%2bred` --- ### 总结 | **场景** | **推荐方法** | **示例** | |------------------------|----------------------------------|---------------------------------------------| | 传递查询参数 | 匿名对象 (`new { key = value }`) | `@Url.Action("Edit", new { id = 10 })` | | 拼接路径片段 | 字符串连接 (`+`) | `@Url.Action("Index") + "/custom-path"` | | 含用户输入的动态参数 | 显式 URL 编码 | `HttpUtility.UrlEncode(userInput)` | > 优先使用 `@Url.Action` 的匿名对象参数生成 URL,安全且自动编码;手动拼接时务必处理特殊字符(参考引用[4])。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值