相关知识
- 对于一个字符串,如何在最后追加一个字符或多个相同字符或一个字符串?在这道题里我们用的是「+=」追加字符串,实际上还可以用
append(),但要注意不能用push_back(),这个只能追加单个字符。
第一轮
第一版(0/20)
#include <cctype>
#include <iostream>
#include <vector>
using namespace std;
bool isDigitSubString(const string &a, const string &b){
for (char c : a) {
if(!isdigit(c)){
return false;
}
}
if (b.find(a) == string::npos) {
return false;
}
return true;
}
int main() {
string s;
cin >> s;
int l = 1;
string longest_strs = "";
for (int k = s.size(); k >= 1; k--) {
for(int i = 0; i <= s.size() - k; i++){
string temp = s.substr(i, k);
if(isDigitSubString(temp, s)){
l = k;
longest_strs += temp;
if(i == s.size() - 1){
cout << longest_strs << ',' << l << endl;
return 0;
}
}
}
}
return 0;
}
- 最里层的分支结构不对。一个字符串,要先满足是数字子串,然后满足是最后一个子串,然后才可以输出,这个显然忽略了最后一个子串不是数字子串的情况。
- 我们把分支改成,首先判断当下框选住的子串是不是数字子串,是则更新,然后结束分支。然后判断当前有没有到框选住最后一个子串而且
l == k(表明找到了数字子串),是则输出。
第二版(0/20)
#include <cctype>
#include <iostream>
#include <vector>
using namespace std;
bool isDigitSubString(const string& a, const string& b) {
for (char c : a) {
if (!isdigit(c)) {
return false;
}
}
if (b.find(a) == string::npos) {
return false;
}
return true;
}
int main() {
string s;
cin >> s;
int l = 1;
string longest_strs = "";
for (int k = s.size(); k >= 1; k--) {
for (int i = 0; i <= s.size() - k; i++) {
string temp = s.substr(i, k);
if (isDigitSubString(temp, s)) {
l = k;
longest_strs += temp;
}
if (i == s.size() - 1 && l == k) {
cout << longest_strs << ',' << l << endl;
return 0;
}
}
}
return 0;
}
- 判断当前有没有到框选住最后一个子串而且
l == k(表明找到了数字子串),是则输出。 - 上面这个逻辑是对的,但是这次改的时候,忽略了一个点——应该改为
i == s.size() - k而非i == s.size() - 1。
第三版(AC)
#include <cctype>
#include <iostream>
#include <vector>
using namespace std;
bool isDigitSubString(const string& a, const string& b) {
for (char c : a) {
if (!isdigit(c)) {
return false;
}
}
if (b.find(a) == string::npos) {
return false;
}
return true;
}
int main() {
string s;
cin >> s;
int l = 1;
string longest_strs = "";
for (int k = s.size(); k >= 1; k--) {
for (int i = 0; i <= s.size() - k; i++) {
string temp = s.substr(i, k);
if (isDigitSubString(temp, s)) {
l = k;
longest_strs += temp;
}
if (i == s.size() - k && l == k) {
cout << longest_strs << ',' << l << endl;
return 0;
}
}
}
return 0;
}
- 这里还有一个值得注意的点,就是
string longest_strs = ""这句初始化空串,不这么也行,因为默认就是空串。 - 但是,这样显示化地写出来,在检查错误的时候可以少费心思。
- 此外,当你要思考一个变量初始化的时候赋什么值的时候,对思考整个题目的逻辑是有帮助的。所以建议写一下。
- 另一个值得注意的知识点——
longest_strs += temp;。我的串怎么跟到你这个串的屁股后面?就这么弄。
第二轮
第一版(AC)
#include <cctype>
#include <iostream>
#include <vector>
using namespace std;
bool isdigitstr(const string& s) {
for (char c : s) {
if (!isdigit(c)) return false;
}
return true;
}
int main() {
string s;
cin >> s;
string result;
int l = s.size() + 1;
for (int k = s.size(); k >= 1; k--) {
for (int i = 0; i <= s.size() - k; i++) {
string str = s.substr(i, k);
if (isdigitstr(str)){
result += str;
l = k;
}
if (i == s.size() - k && l == k) {
cout << result << ',' << l << endl;
return 0;
}
}
}
}
- 比起之前的一版,这一版在写函数的时候,只判断「传入字符串里的字符是不是全为数字」,不判断「传入的a是不是既是数字串又是b的子串」,因为后续的遍历逻辑已经限定了是在子串里找的,不必要把函数写得这么复杂。
- 这一版在写的时候,依然出现很多问题——
比如最后判断i的停止位置是s.size() - k,其实一开始写的是s.size(),后来检查时想到那个「移动的方框」才意识到这个问题。再如两个选择语句最后是串联的,但实际上一开始还是往嵌套那个地方去写,只是因为之前好好思考过这个问题,留下的印象让笔者很快意识到此路不通。再比如最开始是没有l的,因为觉得直接输入k就行,但实际上l是用来辅助判断到此处要不要停下来输出并结束进程的,不引入l思路可能会很复杂。
- 尽管如此,这一轮做到了第一版就AC,仍然是一个非常大的进步。