#P2667. 第2题-字符串翻转
-
2000ms
Tried: 77
Accepted: 19
Difficulty: 4
所属公司 :
米哈游
时间 :2025年3月8日
-
算法标签>思维
第2题-字符串翻转
题解
题目分析
米小游有一个长度为 n 的字符串 s,她需要选择两个区间 [a,b] 和 [c,d],分别对这两个区间执行翻转操作。如果翻转后的字符串与原始字符串相同,则输出 YES 和对应的区间;否则输出 NO。
解题思路
-
翻转操作的性质:
- 翻转操作会改变字符串中某些字符的顺序。
- 如果翻转后的字符串与原始字符串相同,说明翻转操作对字符串的影响被抵消了。
-
寻找回文子串:
- 回文子串是指正读和反读都相同的子串。
- 如果字符串中存在两个互不重叠的回文子串,那么对这两个区间分别执行翻转操作,翻转后的字符串可能与原始字符串相同。
-
实现步骤:
- 遍历字符串,寻找所有长度为 2 或 3 的回文子串。
- 检查是否存在两个互不重叠的回文子串。
- 如果存在,输出
YES和对应的区间;否则输出NO。
代码实现
Python 代码
def main():
n = int(input())
s = input()
palindromes = []
# 寻找所有长度为2或3的回文子串
for i in range(n):
# 检查长度为2的回文
if i + 1 < n and s[i] == s[i + 1]:
palindromes.append((i, i + 1))
# 检查长度为3的回文
if i + 2 < n and s[i] == s[i + 2]:
palindromes.append((i, i + 2))
# 检查是否存在两个互不重叠的回文子串
for i in range(len(palindromes)):
a1 = palindromes[i][0] + 1 # 转换为1-based索引
b1 = palindromes[i][1] + 1
for j in range(i + 1, len(palindromes)):
a2 = palindromes[j][0] + 1
b2 = palindromes[j][1] + 1
if b1 < a2: # 确保区间不重叠
print("YES")
print(a1, b1, a2, b2)
return
# 如果没有找到,则输出NO
print("NO")
if __name__ == "__main__":
main()
java代码
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String s = sc.next();
List<int[]> palindromes = new ArrayList<>();
// 寻找所有长度为2或3的回文子串
for (int i = 0; i < n; i++) {
// 检查长度为2的回文
if (i + 1 < n && s.charAt(i) == s.charAt(i + 1)) {
palindromes.add(new int[]{i, i + 1});
}
// 检查长度为3的回文
if (i + 2 < n && s.charAt(i) == s.charAt(i + 2)) {
palindromes.add(new int[]{i, i + 2});
}
}
// 检查是否存在两个互不重叠的回文子串
for (int i = 0; i < palindromes.size(); i++) {
int a1 = palindromes.get(i)[0] + 1; // 转换为1-based索引
int b1 = palindromes.get(i)[1] + 1;
for (int j = i + 1; j < palindromes.size(); j++) {
int a2 = palindromes.get(j)[0] + 1;
int b2 = palindromes.get(j)[1] + 1;
if (b1 < a2) { // 确保区间不重叠
System.out.println("YES");
System.out.println(a1 + " " + b1 + " " + a2 + " " + b2);
return;
}
}
}
// 如果没有找到,则输出NO
System.out.println("NO");
}
}
C++ 代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
string s;
cin >> n >> s;
vector<pair<int, int>> palindromes;
// 寻找所有长度为2或3的回文子串
for (int i = 0; i < n; ++i) {
// 检查长度为2的回文
if (i + 1 < n && s[i] == s[i+1]) {
palindromes.emplace_back(i, i+1);
}
// 检查长度为3的回文
if (i + 2 < n && s[i] == s[i+2]) {
palindromes.emplace_back(i, i+2);
}
}
// 检查是否存在两个互不重叠的回文子串
for (size_t i = 0; i < palindromes.size(); ++i) {
int a1 = palindromes[i].first + 1; // 转换为1-based索引
int b1 = palindromes[i].second + 1;
for (size_t j = i + 1; j < palindromes.size(); ++j) {
int a2 = palindromes[j].first + 1;
int b2 = palindromes[j].second + 1;
if (b1 < a2) { // 确保区间不重叠
cout << "YES" << endl;
cout << a1 << " " << b1 << " " << a2 << " " << b2 << endl;
return 0;
}
}
}
// 如果没有找到,则输出NO
cout << "NO" << endl;
return 0;
}
题目内容
米小游有一个长度为 n 的字符串 s ,下标从 1 开始。
定义对一个区间 [l,r] 执行翻转操作为将原来的
slsl+1sl+2...sr−1sr变为srsr−1...sl−1sl。
她现在准备选定 4 个 整数 a,b,c,d(1≤a<b<c<d≤n),然后先对区间 [a,b] 执行翻转操作,然后再对区间 [c,d] 执行翻转操作。如果操作完成之后,现在的字符串和初始字符串能够保持相同,输出 “YES”,然后输出这样的 4 个整数,若有多组解,输出任意一个满足条件的解。否则输出“NO ”。
输入描述
第一行一个整数 n(1≤n≤105),表示字符串长度。
第二行一个长度为 n 的字符串 s,保证输入仅由小写字母组成。
输出描述
若可以满足题意,第一行输出“ YES ”,第二行输出 4 个整数,代表 a,b,c,d,以空格隔开,若有多组解,输出任意一个。
若不能,输出“ NO ”
样例1
输入
4
abcd
输出
NO
样例2
输入
13
abbagggfkfggc
输出
YES
1 4 6 12