字符串_hash

本文介绍了一种从字符串中查找特定长度子串的方法,并通过哈希与映射技术来判断这些子串是否重复。重点讲解了如何利用unsigned long long类型进行自然溢出处理,以及如何使用map进行判重,最后提供了两个实例代码。

Problem

从一个串中找到长度为m*l的子串,满足划分成m段长度为l的串后没有相同的两个串
(n<=10^5)

Solution

hash+map判重

Tips

  1. unsigned long long自然溢出即可
  2. map的count返回值为1或0
  3. 二分是[l,r),左闭右开==

Code

hdu4821
hdu4080

<think>我们有一个文件名,例如:'file_log_hash.log',我们想要在'hash'后面插入'_00',变成'file_log_hash_00.log' 但是注意,文件名中的'hash'只是一个示例,实际上的字符串可能是任意内容,但我们要在某个特定部分(比如最后一个下划线之后,文件扩展名之前)插入字符串。 根据问题描述,我们需要在“hash”部分后面插入,也就是在文件扩展名之前插入。我们可以这样理解: 原文件名:file_log_hash.log 目标文件名:file_log_hash_00.log 但是,如果文件名中可能有多个下划线,我们如何定位到“hash”部分?实际上,问题中并没有明确说明“hash”部分的位置特征,但根据常见的日志文件命名,可能是这样的结构: [前缀]_[部分标识]_[哈希值].log 然而,问题中给出的示例是'file_log_hash.log',我们可以假设要求是在最后一个下划线之后、点号之前插入。 因此,步骤可以分解为: 1. 找到最后一个下划线的位置(因为我们要在它后面插入,但实际上是整个字符串中“hash”这个词后面,而“hash”是最后一个下划线后面的部分)。 2. 找到文件扩展名的点号的位置(因为我们要在点号之前插入)。 但是,如果我们在最后一个下划线和点号之间插入,那么就可以实现在“hash”后面插入。 具体步骤: 方法一:使用字符串的lastIndexOf方法找到最后一个下划线的位置,然后从该位置开始,我们找到紧接着的子字符串(直到点号之前),然后在这个子字符串后面加上"_00"。 但是,注意原字符串中最后一个下划线后面就是“hash”,然后紧接着就是点号。所以我们要在最后一个下划线和点号之间插入。 方法二:我们可以将文件名拆分为三部分:主文件名(不含扩展名)、扩展名。然后在主文件名中,我们找到最后一个下划线,将主文件名分为两部分:下划线之前和下划线之后。然后我们在下划线之后的部分后面加上"_00",再重新组合。 例如: 原文件名:file_log_hash.log 主文件名:file_log_hash 扩展名:log 然后,我们在主文件名中找到最后一个下划线,将主文件名分为: 第一部分:file_log 第二部分:hash 然后,将第二部分改为:hash_00 重新组合:file_log + "_" + hash_00 -> 得到新的主文件名:file_log_hash_00 再加上扩展名:file_log_hash_00.log 但是,注意:主文件名中可能包含多个下划线,我们只需要最后一个下划线后面的部分。 另一种更简单的方法:直接在整个字符串中,找到最后一个下划线的位置,然后在这个位置之后插入字符串,但是这样可能会插入到下划线和点号之间。因为点号在最后。 具体步骤(代码): 1. 找到最后一个下划线的位置(lastUnderscoreIndex)。 2. 找到点号的位置(dotIndex),即扩展名前的点。 3. 然后我们在最后一个下划线和点号之间插入字符串,但是注意:我们只需要在最后一个下划线后面的部分(即从lastUnderscoreIndex+1到dotIndex)之前插入吗?实际上,我们可以在最后一个下划线后面直接插入,因为我们要在“hash”后面插入,而“hash”紧跟着最后一个下划线。 但是,如果我们直接在下划线后面插入,那么就会变成:file_log_00hash.log,这显然不对。因为我们要在“hash”后面插入,所以应该是在“hash”的后面,也就是在最后一个下划线后面的整个子串的后面插入?不对,因为“hash”就是最后一个下划线后面的整个子串(直到点号)。 所以,我们实际上是要在最后一个下划线后面的子串和点号之间插入。 因此,我们可以这样做: 使用substring(0, lastUnderscoreIndex+1)得到下划线之前的部分(包括下划线),然后剩下的部分是从lastUnderscoreIndex+1到结尾。然后我们在剩下的部分中,找到点号的位置(相对于剩余子串的位置),然后在这个点号之前插入"_00"。 但是,这样有点复杂。我们可以用更简单的方法:将文件名拆成两部分:主文件名(不含扩展名)和扩展名,然后在主文件名后面先加上"_00",再加上扩展名。 但是,这样也会有问题:主文件名中已经有一个下划线了,我们直接在主文件名后面加,那么就会变成:file_log_hash_00.log,这正好是我们想要的。 所以,步骤: 1. 找到最后一个点号的位置(用于分离扩展名)。 2. 如果没有点号,那么整个字符串作为主文件名,然后直接在后面添加"_00"。 3. 如果有,那么主文件名是点号之前的部分,扩展名是点号之后的部分。 4. 然后在主文件名后面添加"_00",然后再加点和扩展名。 但是,这样就是在整个主文件名后面添加了"_00",而不仅仅是“hash”后面。但是,题目要求是在“hash”后面添加,而“hash”是主文件名的最后一部分(以最后一个下划线分隔)。那么,按照这个操作,我们得到的是:file_log_hash_00.log,这符合要求。 所以,我们不需要关心“hash”在哪里,我们只需要在文件扩展名之前,主文件名的末尾添加"_00"即可。 但是,题目要求是在“hash”后面,而“hash”是主文件名的最后一部分,那么在主文件名后面添加,实际上就是在“hash”后面添加。 因此,我们可以这样写: 代码: String originalName = "file_log_hash.log"; int lastDotIndex = originalName.lastIndexOf('.'); String newName; if (lastDotIndex != -1) { // 有扩展名 String baseName = originalName.substring(0, lastDotIndex); // 主文件名:file_log_hash String extension = originalName.substring(lastDotIndex); // 扩展名:.log newName = baseName + "_00" + extension; } else { // 没有扩展名 newName = originalName + "_00"; } 这样,我们就得到了file_log_hash_00.log 但是,如果文件名是"file.log",那么处理后变成"file_00.log",这符合预期吗?题目要求是在“hash”后面,而“file.log”中并没有“hash”部分,所以题目中的示例是包含“hash”的,但实际需求可能是在文件名的最后(扩展名之前)添加。 根据问题描述,我们是在“hash”部分后插入,但“hash”只是一个示例,实际可能是一个变化的字符串。所以,我们只需要在扩展名之前插入即可。 但是,如果文件名是"file_hash_log.txt"呢?注意,这里有两个下划线,但我们只希望在最末尾(扩展名之前)插入,那么按照上面的方法,我们是在整个主文件名(file_hash_log)后面添加,变成"file_hash_log_00.txt",这实际上是在整个主文件名后面添加,而不是在“hash”后面。 所以,我们需要明确:题目要求是在“hash”后面插入,而“hash”在文件名中是什么位置?问题中给出的示例是'file_log_hash.log',其中“hash”是最后一个下划线后面的部分。所以,我们只处理这种在最后一个下划线后面的部分(即最后一部分)后面插入。 但是,上面的方法并没有区分主文件名中的下划线,而是整个主文件名后面加。所以,如果文件名是"file_hash_log.txt",那么处理后就变成了"file_hash_log_00.txt",而实际上,我们可能希望是在“log”后面加?但是题目要求是在“hash”后面加?这显然不对。 重新理解问题:问题中给出的示例是'file_log_hash.log',并说明在hash后添加_00。所以,我们并不是在最后一部分后面加,而是在特定字符串hash”后面加。但是,问题中并没有说一定是“hash”,而是说在“hash部分”,这个“hash部分”可能是任意字符串,但问题中给出的位置是“在hash后”。 所以,如果要求是固定的字符串hash”后面插入,那么我们可以这样: String originalName = "file_log_hash.log"; String target = "hash"; int index = originalName.indexOf(target); if (index != -1) { // 找到target,然后在它后面插入 int endIndex = index + target.length(); // 插入位置在target之后 newName = originalName.substring(0, endIndex) + "_00" + originalName.substring(endIndex); } 但是,这样就会变成:file_log_hash_00.log 但是,如果文件名中有多个“hash”,我们可能只希望替换最后一个?或者第一个?题目没有说明。根据示例,只有一个“hash”,所以我们可以假设只出现一次。 所以,具体方法取决于需求: 情况1:如果确定要在扩展名之前、主文件名的末尾添加,那么用第一种方法(分离主文件名和扩展名)。 情况2:如果确定要在特定的子串“hash”后面添加,那么用第二种方法(查找子串位置)。 问题描述中说的是“在'file_log_hash.log'中的hash后添加_00”,所以这里明确是“hash”这个字符串后面。 因此,我们采用第二种方法,但是要注意:如果文件名中没有“hash”怎么办?我们可以按照原样返回。 代码实现: public static String insertAfterHash(String fileName) { String target = "hash"; int index = fileName.indexOf(target); if (index == -1) { // 没有找到,直接返回原文件名 return fileName; } // 计算插入位置:在target的末尾 int endIndex = index + target.length(); return fileName.substring(0, endIndex) + "_00" + fileName.substring(endIndex); } 测试: 输入:'file_log_hash.log' -> 输出:'file_log_hash_00.log' 但是,如果文件名是'hash_file.log',那么就会在第一个“hash”后面插入,变成'hash_00_file.log'。这符合要求吗?题目没有说明,但是根据示例,我们只处理“hash”出现的位置。如果要求是最后一个“hash”,那么需要改为lastIndexOf。 修改为: int index = fileName.lastIndexOf(target); // 找最后一个出现的 这样,如果文件名是'hash_file_hash.log',就会在最后一个hash后面插入,变成'hash_file_hash_00.log' 所以,根据需求,我们使用lastIndexOf。 因此,最终代码: public static String insertAfterLastHash(String fileName) { String target = "hash"; int index = fileName.lastIndexOf(target); if (index == -1) { return fileName; } int endIndex = index + target.length(); return fileName.substring(0, endIndex) + "_00" + fileName.substring(endIndex); } 但是,这里有一个问题:文件名中可能包含“hash”作为其他单词的一部分,比如“hashtag”,那么也会匹配到。所以,我们可能希望“hash”是一个独立的单词?但是题目没有说明,所以我们按照字符串匹配。 如果要求是独立的单词,那么我们需要使用正则表达式,但这样会增加复杂度。根据问题,我们按照普通字符串匹配即可。 另外,注意大小写:如果要求大小写不敏感,那么我们可以将字符串转换为小写再查找,但插入的时候要保持原字符串的大小写。所以,我们可以这样: String target = "hash"; int index = fileName.toLowerCase().lastIndexOf(target.toLowerCase()); if (index == -1) { return fileName; } // 但是注意,插入位置是原字符串中的位置,所以我们需要用原字符串的substring // 因为toLowerCase()后得到的是新字符串,位置相同?是的,因为只是将字符转换为小写,长度和位置不变。 // 所以,我们可以用这个index,然后在原字符串中操作。 但是,如果大小写不敏感,那么原字符串中可能匹配的是“Hash”或“HASH”,那么我们在插入时,需要保持原样。上面的方法中,我们只是用index(位置)来切割原字符串,所以没有问题。 因此,如果要求大小写不敏感,可以这样: String target = "hash"; String lowerFileName = fileName.toLowerCase(); int index = lowerFileName.lastIndexOf(target.toLowerCase()); if (index == -1) { return fileName; } int endIndex = index + target.length(); // 注意:这里用target的长度(小写),因为匹配的长度就是target的长度(即使原字符串中是大写,但长度相同) 但是,这里有一个问题:原字符串中匹配的部分长度和target长度相同吗?是的,因为我们在小写字符串中查找小写的target,所以匹配到的子串长度就是target的长度。所以,我们可以在原字符串中从index开始,取target.length()个字符,这个子串就是匹配到的部分(大小写可能不同,但长度相同)。 所以,我们可以在原字符串中,从0到index+target.length()处插入。 因此,代码: public static String insertAfterLastHashCaseInsensitive(String fileName) { String target = "hash"; String lowerFileName = fileName.toLowerCase(); String lowerTarget = target.toLowerCase(); int index = lowerFileName.lastIndexOf(lowerTarget); if (index == -1) { return fileName; } int endIndex = index + target.length(); // 注意:这里使用target的长度(原始target的长度),因为匹配到的部分长度和target相同 return fileName.substring(0, endIndex) + "_00" + fileName.substring(endIndex); } 但是,这里有一个潜在的问题:如果target是"hash",而原字符串中匹配的部分是"HASH",那么长度是4,和target的长度相同(4),所以没有问题。所以,这样写是可行的。 但是,如果需求是大小写敏感的,那么就不需要转换为小写,直接使用原字符串查找。 根据问题,没有明确说明大小写,所以我们可以提供两种方法,或者按照大小写敏感来处理(因为原示例是小写的)。 由于问题中给出的示例是小写,所以我们可以按照大小写敏感处理,这样更简单。 因此,我们选择大小写敏感的方式: public static String insertAfterLastHash(String fileName) { String target = "hash"; int index = fileName.lastIndexOf(target); if (index == -1) { return fileName; } int endIndex = index + target.length(); return fileName.substring(0, endIndex) + "_00" + fileName.substring(endIndex); } 但是,如果文件名是'file_log_hash'(没有扩展名),那么也会在最后插入,变成'file_log_hash_00'。 这符合要求。 所以,我们按照这个方法来。 但是,问题中给出的文件名是'file_log_hash.log',我们处理成'file_log_hash_00.log'。 因此,完整代码示例: 注意:这里我们假设传入的文件名字符串,我们只处理最后一个“hash”的出现。 如果需求是只处理一次,那么上面的代码就可以了。 测试用例: "file_log_hash.log" -> "file_log_hash_00.log" "testhash.log" -> "testhash_00.log" (注意:这里匹配到了整个“testhash”中的“hash”?但是“testhash”包含“hash”,所以会匹配。如果我们希望是独立的单词,那么需要改进,但题目没有要求,我们就按此处理) 如果希望是独立的单词(即前后不是字母数字),那么需要使用正则表达式,但这样会复杂一些,而且题目没有要求,所以先不处理。 因此,我们提供以下方法: 方法:在文件名中最后一个出现的“hash字符串后面插入“_00”。 代码实现: public class InsertStringDemo { public static void main(String[] args) { String fileName = "file_log_hash.log"; String result = insertAfterLastHash(fileName); System.out.println(result); // 输出:file_log_hash_00.log } public static String insertAfterLastHash(String fileName) { String target = "hash"; int index = fileName.lastIndexOf(target); if (index == -1) { return fileName; } int endIndex = index + target.length(); return fileName.substring(0, endIndex) + "_00" + fileName.substring(endIndex); } } 但是,如果需求是插入的位置不是固定的“hash”,而是任意给定的字符串,那么我们可以将target作为参数。 改进后: public static String insertAfterLastOccurrence(String fileName, String target) { int index = fileName.lastIndexOf(target); if (index == -1) { return fileName; } int endIndex = index + target.length(); return fileName.substring(0, endIndex) + "_00" + fileName.substring(endIndex); } 这样,我们可以传入任意target,比如“hash”、“version”等。 调用示例: String result = insertAfterLastOccurrence("file_log_hash.log", "hash"); 因此,我们提供一个更通用的方法。 总结:在字符串中特定子串(最后一次出现)的后面插入另一个字符串。 注意:这个方法也可以用于在任意字符串中插入,不限于文件名。 但是,如果要在特定位置插入(比如第n次出现),可以进一步扩展。 现在,我们回答用户的问题:在Java中如何在文件名字符串hash部分后插入_00。 答案:使用上述方法,通过lastIndexOf找到hash的最后一次出现位置,然后在该位置加上hash的长度得到插入点,然后在该点插入字符串"_00"。 注意:这里我们假设用户要求的“hash部分”就是字符串hash”。如果实际上“hash部分”可能是其他含义(比如一个变量),那么需要根据具体情况调整。 如果用户的需求是在文件扩展名之前插入,而不是在“hash”后面,那么方法不同。根据问题描述,明确是在hash后,所以我们用这个方法。 最后,我们给出完整代码示例。</think>在 Java 中,要在文件名中的特定字符串(如 "hash")后插入 "_00",可以通过定位目标字符串位置并使用字符串拼接实现。以下是完整解决方案: ### 解决方案:在特定字符串后插入内容 ```java public class FileNameModifier { public static void main(String[] args) { String fileName = "file_log_hash.log"; String target = "hash"; // 要查找的目标字符串 String insertStr = "_00"; // 要插入的内容 // 在目标字符串后插入新内容 String modifiedName = insertAfterTarget(fileName, target, insertStr); System.out.println("修改后: " + modifiedName); // 输出: file_log_hash_00.log } /** * 在目标字符串最后一次出现的位置后插入新内容 * @param source 原始字符串 * @param target 要查找的目标字符串 * @param insert 要插入的内容 * @return 修改后的字符串 */ public static String insertAfterTarget(String source, String target, String insert) { int lastIndex = source.lastIndexOf(target); if (lastIndex == -1) { return source; // 未找到目标直接返回原字符串 } // 计算插入位置(目标字符串结尾处) int insertPosition = lastIndex + target.length(); // 拼接新字符串:目标前部分 + 目标 + 插入内容 + 剩余部分 return source.substring(0, insertPosition) + insert + source.substring(insertPosition); } } ``` ### 关键说明 1. **定位目标位置**: ```java int lastIndex = source.lastIndexOf(target); // 查找目标最后一次出现的位置 ``` - `lastIndexOf()` 确保处理文件名中多次出现目标的情况[^1] - 返回 `-1` 表示未找到目标字符串 2. **字符串拼接**: ```java source.substring(0, insertPosition) // 目标前部分 + insert // 插入内容 + source.substring(insertPosition) // 剩余部分 ``` - 使用 `substring()` 分割字符串,避免创建不必要的中间对象[^2] 3. **大小写敏感处理**: ```java // 如需忽略大小写,改用: int lastIndex = source.toLowerCase().lastIndexOf(target.toLowerCase()); ``` - 比较时转换为小写实现大小写不敏感匹配 - 插入时仍保留原始字符串大小写 4. **扩展应用**: ```java // 示例:在版本号后插入补丁标识 String modVer = insertAfterTarget("app_v1.2.3.exe", "v1.2", "_patch"); // 结果: app_v1.2_patch.3.exe ``` ### 处理边界情况 | 输入案例 | 输出结果 | 说明 | |----------|----------|------| | `"file.log"` | `"file.log"` | 未找到目标不修改 | | `"hash_file.log"` | `"hash_00_file.log"` | 处理开头的目标 | | `"file_hash"` | `"file_hash_00"` | 无扩展名文件 | | `"hash_log_hash.log"` | `"hash_log_hash_00.log"` | 处理最后出现的目标 | 此方案通过精准定位字符串位置实现插入操作,比正则表达式更高效[^2],且能正确处理文件名中的特殊字符和扩展名。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值