题目背景
L1-064 估值一亿的AI核心代码
分数 20
全屏浏览
切换布局
作者 陈越
单位 浙江大学
以上图片来自新浪微博。
本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是:
- 无论用户说什么,首先把对方说的话在一行中原样打印出来;
- 消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
- 把原文中所有大写英文字母变成小写,除了
I
; - 把原文中所有独立的
can you
、could you
对应地换成I can
、I could
—— 这里“独立”是指被空格或标点符号分隔开的单词; - 把原文中所有独立的
I
和me
换成you
; - 把原文中所有的问号
?
换成惊叹号!
; - 在一行中输出替换后的句子作为 AI 的回答。
输入格式:
输入首先在第一行给出不超过 10 的正整数 N,随后 N 行,每行给出一句不超过 1000 个字符的、以回车结尾的用户的对话,对话为非空字符串,仅包括字母、数字、空格、可见的半角标点符号。
输出格式:
按题面要求输出,每个 AI 的回答前要加上 AI:
和一个空格。
输入样例:
6
Hello ?
Good to chat with you
can you speak Chinese?
Really?
Could you show me 5
What Is this prime? I,don 't know
输出样例:
Hello ?
AI: hello!
Good to chat with you
AI: good to chat with you
can you speak Chinese?
AI: I can speak chinese!
Really?
AI: really!
Could you show me 5
AI: I could show you 5
What Is this prime? I,don 't know
AI: what Is this prime! you,don't know
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB
思路
世界上怎么会有这么讨厌的L1题????
基本思路
先格式化(包括去除空格,大小写转换,问号转感叹号),再进行其它替换
使用getline读入一行进行处理即可。
然后就是最讨厌的坑点
坑点
1、消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
然后这句话坑就多了。首先,要考虑到所有的“ XXX XXX ”,前面、中间、后面都会出现不止一个空格,该语句需要变成:“XXX XXX”。
另外还要考虑,首个非字母元素不一定是字母,例如:“ -Hello ”,需要考虑是否保留首空格。
然后标点前的空格要删除,意味着我们面临这样的问题:
首字母之前的空格要全部删除,但是其它字母之前的空格要保留。因此我们给字符串加入首个空格,令所有字母前的空格保留。这样就会让首字母前一定有个空格,然后其它字母前有个空格,符合格式。最后输出时,输出“AI:”(:后无空格),然后直接输出字符串即可。
所有标点符号之前的空格要全部删除。但是根据前面的规则,我们的字符串必须以空格开始。因此在最后输出时,必须判断是否有前置空格,若没有,需要先输出空格再接字符串内容。
2、
- 把原文中所有独立的
can you
、could you
对应地换成I can
、I could
—— 这里“独立”是指被空格或标点符号分隔开的单词; - 把原文中所有独立的
I
和me
换成you;
非常讨厌要求,让我时间浪费。
什么是独立呢?该题的判断是:前后不是字母即可,未考虑数字或者标点。
然后既然要判断前后,那么我考虑了越界问题(比如首字母无前字母,判断前独立可能有误。末尾字母无后字母,判断后独立也可能有误),导致代码相当复杂。其实我也找到了另外的代码,发现这道题也可以不考虑越界问题。但总觉得不太严谨,就还是保留越界的判断。
最后这里还有一个关键性坑点:在I / me 转为you之后,会导致可能“can I”先转换为“can you”, 然后又被转为“I can”。
解决该问题,只需要将所有 I / me 转为的 you 暂时写为 yoU 即可。然后在输出时特殊处理U。
另外,如果你精通stringstream,对于去除空格的方法可能会更简单,但是不推荐使用,因为标点符号之前的空格要去除,还是要判断再处理。
完整代码
#include <iostream>
#include <string>
using namespace std;
bool zimu(char c) {
if (c >= 'A' && c <= 'Z') {
return true;
}
if (c >= 'a' && c <= 'z') {
return true;
}
return false;
}
bool shuzi(char c) {
if (c >= '0' && c <= '9') {
return true;
}
return false;
}
int main() {
int n;
cin >> n;
getchar();
for (int i = 0; i < n; i++) {
string s;
getline(cin, s);
cout << s << endl;
s = " " + s; // 保证每个都是空格开始
for (int index = 0; index < s.length(); index++) {
// 先消除空格,大写变小写,问号变感叹号。
if (s[index] == ' ') {
if (index + 1 >= s.length()) {
s.erase(index, 1);
index--;
} else {
if (!zimu(s[index + 1]) && !shuzi(s[index + 1])) {
s.erase(index, 1);
index--;
}
}
} else if (s[index] >= 'A' && s[index] <= 'Z' && s[index] != 'I') {
s[index] += 32;
} else if (s[index] == '?') {
s[index] = '!';
}
}
// 独立I -》 you
for (int index = 0; index < s.length(); index++) {
index = s.find("I", index);
if (index == -1) {
break;
} else {
bool r = true;
if (index - 1 >= 0 && zimu(s[index - 1]))
r = false;
if (index + 1 < s.length() && zimu(s[index + 1]))
r = false;
if (r)
s.replace(index, 1, "yoU");
}
}
// 独立me -》 you
for (int index = 0; index < s.length(); index++) {
index = s.find("me", index);
if (index == -1) {
break;
} else {
bool r = true;
if (index - 1 >= 0 && zimu(s[index - 1]))
r = false;
if (index + 2 < s.length() && zimu(s[index + 2]))
r = false;
if (r)
s.replace(index, 2, "yoU");
}
}
// 独立can you -》 I can
for (int index = 0; index < s.length(); index++) {
index = s.find("can you", index);
if (index == -1) {
break;
} else {
bool r = true;
if (index - 1 >= 0 && zimu(s[index - 1]))
r = false;
if (index + 7 < s.length() && zimu(s[index + 7]))
r = false;
if (r)
s.replace(index, 7, "I can");
}
}
// 独立could you -》 I could
for (int index = 0; index < s.length(); index++) {
index = s.find("could you", index);
if (index == -1) {
break;
} else {
bool r = true;
if (index - 1 >= 0 && zimu(s[index - 1]))
r = false;
if (index + 9 < s.length() && zimu(s[index + 9]))
r = false;
if (r)
s.replace(index, 9, "I could");
}
}
cout << "AI:";
if (s[0] != ' ') {
cout << ' ';
}
for (int index = 0; index < s.length(); index++) {
if (s[index] == 'U') {
cout << 'u';
} else {
cout << s[index];
}
}
cout << endl;
}
}
嗯,主要考察了string一些不太常用的函数(replace,erase)。。。这方面还是太弱了。。。