本题要求判断给定的字符串是否能够由两个长度都至少为 2 的回文串前后拼接而成。
aa、aba、abba 等。例如,字符串 aabbb 可以拆分成 aa 和 bbb,两者都是回文且长度 ≥ 2,因此满足条件。
我们需要对输入的每一个字符串,判断是否存在这样一种拆分方式。
由于数据规模非常小(n ≤ 10,字符串长度 ≤ 100),我们可以直接使用暴力枚举的方法。
对于每个字符串 s,设其长度为 m:
j 表示第一个回文串的长度,其取值范围为 2 到 m-2(保证左右两边长度都至少为 2)。s1 = s[0, j]s2 = s[j, m-j]s1 和 s2 是否都是回文串。判断回文可以直接将字符串反转后与原串比较,或者用双指针对比首尾字符。Yes;否则输出 No。这种方法虽然简单,但在题目给定的数据范围内完全可行。
n。n 个字符串,对于每个字符串 s:
m = s.size()。fl = 0,表示是否找到合法分割。j 从 2 到 m-2:
s1 和 s2。s1 的反转串 t1(倒序遍历 s1 拼接)。s2 的反转串 t2。t1 == s1 且 t2 == s2,则 fl = 1,跳出循环。fl 的值输出 Yes 或 No。回文判断的另一种写法(双指针):
cpp1bool isPalindrome(string s) { 2 int i = 0, j = s.size() - 1; 3 while (i < j) { 4 if (s[i] != s[j]) return false; 5 i++; j--; 6 } 7 return true; 8}
也可以直接使用 C++ 的 reverse 函数或 string 构造函数生成反转串进行比较。
在最坏情况下,n=10,m=100,计算量约为 10 × 100² = 100,000,完全可以在 1 秒内轻松运行完成,满足题目要求。
根据题目给出的参考代码,我们添加了详细的注释以便理解。
cpp1#include <bits/stdc++.h> 2using namespace std; 3 4int main() { 5 int n; 6 cin >> n; 7 for (int i = 1; i <= n; i++) { 8 string s; 9 cin >> s; 10 int m = s.length(); 11 int fl = 0; // 标记是否找到合法分割,0表示未找到,1表示找到 12 13 // 枚举分割点j,j是第一个回文串的长度 14 // 从2开始,保证第一个串长度>=2 15 // 到m-2结束,保证第二个串长度>=2 16 for (int j = 2; j <= m - 2; j++) { 17 string s1 = s.substr(0, j); // 截取前j个字符 18 string s2 = s.substr(j, m - j); // 截取剩余字符 19 20 // 构造s1的反转串 21 string t1 = ""; 22 for (int k = (int)s1.size() - 1; k >= 0; k--) { 23 t1 += s1[k]; 24 } 25 26 // 构造s2的反转串 27 string t2 = ""; 28 for (int k = (int)s2.size() - 1; k >= 0; k--) { 29 t2 += s2[k]; 30 } 31 32 // 如果两个都是回文串,则标记成功并跳出循环 33 if (t1 == s1 && t2 == s2) { 34 fl = 1; 35 break; 36 } 37 } 38 39 // 根据标记输出结果 40 if (fl) 41 cout << "Yes\n"; 42 else 43 cout << "No\n"; 44 } 45 return 0; 46}
s.substr(0, j):从索引 0 开始截取长度为 j 的子串,作为第一个部分。s.substr(j, m - j):从索引 j 开始截取剩余部分,作为第二个部分。for 循环通过从尾到头遍历的方式手动反转字符串,然后与原串比较来判断回文。fl = 1 并 break 跳出循环,避免多余计算。fl 输出 Yes 或 No。本题主要考察对字符串子串截取和回文判断的基本操作。由于数据范围极小,暴力枚举分割点并逐一验证是最直接、最可靠的解法。读者在解决类似问题时,若数据范围较大,可以考虑优化回文判断(如预处理哈希或马拉车算法),但本题中则完全不需要。