PTAL1-064 估值一亿的AI核心代码---复杂的字符串处理
L1-064 估值一亿的AI核心代码
以上图片来自新浪微博。
本题要求你实现一个稍微更值钱一点的 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
通过这题学到了string的几个字符串处理的函数
- substr(index,n) 得到index开始,长度为n的子串
- erase(index,n) 删除index开始的num个字符
- insert(index,ch) 在index处插入字符ch
- replace(index,n,str2) 用str2字符串替换index开始的n个字符
- isalnum(char ch) 判断字符ch是否为字母或数字,是返回1,否返回0
- isalpha(char ch) 判断字符ch是否为英文字符,是返回1,否返回0
- isdigit(char ch) 判断字符ch是否为十进制数字字符,是返回1,否返回0
题目的数据中是存在标点符号的,完全不用这些函数,想做出这题就很难了
AC Code:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <queue>
#include <climits>
#include <set>
#include <stack>
#include <string>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
static const int MAX_N = 15;
string str;
bool judge(int pos, int p, int len) {
/*越界判断*/
if(pos + p < len && pos - 1 >= 0) return (!isalnum(str[pos - 1]) && !isalnum(str[pos + p]));
else if(pos - 1 >= 0) return (!isalnum(str[pos - 1]));
else if (pos + p < len) return (!isalnum(str[pos + p]));
else return true;
}
int main() {
int t;
scanf("%d", &t);
getchar();
while (t--) {
getline(cin, str);
cout << str << endl;
int len = str.length();
while (len > 1 && str[0] == ' ') { //去掉行前空格
str.erase(0, 1);
len--;
}
int i = len - 1;
while (i >= 0 && str[i] == ' ') { //去掉行末空格
str.erase(i, 1);
--i;
}
i = 0;
len = str.length();
for (; i < len; ++i) {
while (str[i] == ' ') { //去掉单词间的多余空格
if (i + 1 < len && !isalnum(str[i + 1])) {
//这里不能直接判断是空格,因为是标点符号的话,空格也需要去掉
str.erase(i, 1);
len--;
}
else break;
}
if(str[i] != 'I' && str[i] >= 'A' && str[i] <= 'Z') //转小写
str[i] += 32;
else if (str[i] == '?') str[i] = '!';
}
/*
这题最坑的地方,需要两个for循环,把所有字符转小写了,再判断里面的me,can you等单词
不然CAN YOU这种数据...
*/
for (i = 0; i < len; ++i) {
if (str[i] == 'I' && judge(i, 1, len)) str.replace(i, 1, "you");
/*截取字符,注意判断,不然会数组越界*/
else if (i + 1 < len && str.substr(i, 2) == "me" && judge(i, 2, len)) str.replace(i, 2, "you");
else if (i + 6 < len && str.substr(i, 7) == "can you" && judge(i, 7, len)) str.replace(i, 7, "I can");
else if (i + 8 < len && str.substr(i, 9) == "could you" && judge(i, 9, len)) str.replace(i, 9, "I could");
len = str.length();
}
printf("AI: ");
cout << str << endl;
}
return 0;
}