最近的CCCC天梯赛又出了非常恶心的字符串题~
在编程竞赛(特别是CCCC天梯赛)中,字符串操作类题目往往看似简单却暗藏陷阱。本文将以Python、Java、C++ 三剑客为例,总结高频字符串操作的优雅实现方案,助你快速攻克字符串类难题。
一、子串替换:精准狙击第一个目标
需求描述
将字符串中第一个出现的子串A替换为子串B,若A不存在则保持原字符串。
Python
def replace_first_substring(s, A, B):
return s.replace(A, B, 1) # 第三个参数控制替换次数
# 示例:将首个"apple"换为"orange"
print(replace_first_substring("apple banana apple", "apple", "orange")) # orange banana apple
Java
方案一:正则安全版(避免特殊字符干扰)
import java.util.regex.*;
public class StringUtils {
public static String replaceFirstSubstring(String str, String A, String B) {
return str.replaceFirst(Pattern.quote(A), Matcher.quoteReplacement(B));
}
}
// 示例:替换首个包含正则符号的字符串
System.out.println(replaceFirstSubstring("a+b*c", "+b*", "-")); // a-c
方案二:高效直操作版
public static String replaceFirstSubstring(String str, String A, String B) {
int index = str.indexOf(A);
return index != -1 ? str.substring(0, index) + B + str.substring(index + A.length()) : str;
}
C++
#include <string>
using namespace std;
string replace_first_substring(string str, const string& A, const string& B) {
size_t pos = str.find(A);
if (pos != string::npos) {
str.replace(pos, A.length(), B);
}
return str;
}
// 示例:替换首个"cpp"
cout << replace_first_substring("cpp python cpp", "cpp", "C++"); // C++ python cpp
二、删除操作:定点清除与精确爆破
场景一:删除首个指定子串
Python
def delete_first_substring(s, A):
return s.replace(A, "", 1) # 第三个参数控制删除次数
print(delete_first_substring("test_test", "test")) # _test
Java
public static String deleteFirstSubstring(String str, String A) {
int index = str.indexOf(A);
return index != -1 ? str.substring(0, index) + str.substring(index + A.length()) : str;
}
// 示例:删除首个"bug"
System.out.println(deleteFirstSubstring("bug1 bug2", "bug")); // 1 bug2
C++
string delete_first_substring(string str, const string& A) {
size_t pos = str.find(A);
if (pos != string::npos) {
str.erase(pos, A.length());
}
return str;
}
场景二:删除指定索引字符
Python
s = "012345"
s = s[:3] + s[4:] # 删除索引3的字符
print(s) # 01245
Java
String str = "ABCDEF";
String newStr = str.substring(0, 2) + str.substring(3); // 删除索引2
System.out.println(newStr); // ABDEF
C++
string str = "Hello!";
str.erase(5, 1); // 删除索引5的字符(!)
cout << str; // Hello
三、切片操作
截取区间 [start, end)
的子串
Python
s = "abcdef"
print(s[2:5]) # cde (索引2到4)
Java
String str = "ABCDEF";
String sub = str.substring(1, 4); // 索引1到3
System.out.println(sub); // BCD
C++
string str = "123456";
string sub = str.substr(2, 3); // 从索引2开始取3个字符
cout << sub; // 345
四、字符串翻转:镜像世界的魔法
Python
s = "hello"
reversed_str = s[::-1] # 切片步长-1实现反转
print(reversed_str) # olleh
Java
String str = "reverse";
String reversed = new StringBuilder(str).reverse().toString();
System.out.println(reversed); // esrever
C++
string str = "CPP";
reverse(str.begin(), str.end()); # 原地反转
cout << str; // PPC
关键点总结
操作类型 | Python优势 | Java技巧 | C++特性 |
---|---|---|---|
替换 | replace 次数控制 | 正则转义防陷阱 | find +replace 链式操作 |
删除 | 空替换复用逻辑 | indexOf 边界检查 | erase 精准清除 |
切片 | [start:end] 极简语法 | 双参数substring | substr 起始位置+长度 |
翻转 | 负步长切片 | StringBuilder 工具类 | reverse 算法直接修改 |
避坑指南
-
Java的substring索引陷阱
str.substring(a, b)
的结束索引是独占的(即包含a不包含b),与Python切片行为一致 -
C++的substr参数特殊性
第二个参数表示截取长度而非结束位置,需特别注意str.substr(2, 3)
表示从索引2开始取3个字符 -
正则敏感字符处理
当替换内容包含$
、\
等特殊符号时,Java必须使用Matcher.quoteReplacement