PTAL1-064 估值一亿的AI核心代码---复杂的字符串处理

                                         L1-064 估值一亿的AI核心代码

PTAL1-064 估值一亿的AI核心代码---复杂的字符串处理

以上图片来自新浪微博。

本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是:

  • 无论用户说什么,首先把对方说的话在一行中原样打印出来;
  • 消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
  • 把原文中所有大写英文字母变成小写,除了 I
  • 把原文中所有独立的 can youcould you 对应地换成 I canI could—— 这里“独立”是指被空格或标点符号分隔开的单词;
  • 把原文中所有独立的 Ime 换成 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;
}