集训17--7-8 估值一亿的AI核心代码(正则表达式+字符串模拟)

以上图片来自新浪微博。

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

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

 这题有两个坑点:

1、can you,could you, I, me的替换是在将字母转换成小写字母后进行的,如果原文中有 ME ,最后也是会被替换成you的。

2、can you,could you,I,me 的替换是独立的,假设原文中含有 can you,我们将其替换成I can,那么我们就不能再接着把I替换成 you,得到you can,这是错误的。

最近刚学了正则表达式,发现用来解这题真的非常合适,代码只有二十多行,有兴趣可以了解一下。贴个代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	getchar();
	while(n--)
	{
		string str;
		getline(cin,str);
		cout<<str<<endl;
		str=regex_replace(str,regex(" +")," ");
		str=regex_replace(str,regex(" ([^\\w ])"),"$1");
		while(str[0]==' ') str.erase(str.begin());
		while(str.back()==' ') str.pop_back();
		for(int i=0;i<str.size();i++)
			if(str[i]>='A'&&str[i]<='Z'&&str[i]!='I')
				str[i]+=' ';
		//本来是要替换成I can的,但是为了防止下一步继续将I变成you
		//先替换成% can,后续再把%替换成I
		str=regex_replace(str,regex("\\bcan you\\b"),"% can");  
		str=regex_replace(str,regex("\\bcould you\\b"),"% could");
		str=regex_replace(str,regex("\\b(I|(me))\\b"),"you");
		for(int i=0;i<str.size();i++)
			if(str[i]=='?') str[i]='!';
			else if(str[i]=='%') str[i]='I';
		cout<<"AI: "<<str<<endl;
	}
	return 0;
}

不会正则表达式也没关系,理清思路就行,代码也不算长,五十行左右

我们先做这几个操作

  • 消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
  • 把原文中所有大写英文字母变成小写,除了 I
  • 把原文中所有的问号 ? 换成惊叹号 !

再做替换操作

在替换的时候是针对做完上述操作后的字符串原文进行替换的,具体看代码

  • 把原文中所有独立的 can youcould you 对应地换成 I canI could—— 这里“独立”是指被空格或标点符号分隔开的单词;
  • 把原文中所有独立的 I 和 me 换成 you
#include<bits/stdc++.h>
using namespace std;
//check 函数用来判断是否独立。
bool check(string& temp,int l,int r)
{
	if((l<0||!isalnum(temp[l]))&&(r>=temp.size()||!isalnum(temp[r])))
		return true;
	return false;
}
int main()
{
	int n;
	cin>>n;
	getchar();
	while(n--)
	{
		string str;
		getline(cin,str);
		cout<<str<<endl;

		//第一大步操作
		string temp;
		for(int i=0;i<str.size();i++)
			if(str[i]==' ')
			{
				//消除多余空格,消除符号前的空格
				if(!temp.size()) continue;
				while(i<str.size()&&str[i]==' ') i++;
				if(i==str.size()) break;
				if(isalnum(str[i])) temp+=' ';
				i--;
			}else
			{
				if(str[i]>='A'&&str[i]<='Z'&&str[i]!='I')
					temp+=str[i]+' ';   //大写转小写
				else if(str[i]=='?') temp+='!';   //问号改为感叹号
				else temp+=str[i];     //其他字符不需要变
			}


		//进行第二大步操作
		//我们在这里只看原文,把答案都放进res中,就不用考虑can you变成I can后I再次被替换的情况了。
		string res;
		for(int i=0;i<temp.size();i++)
			if(temp[i]=='I'&&check(temp,i-1,i+1)) 
				res+="you";
			else if(i+1<temp.size()&&temp.substr(i,2)=="me"&&check(temp,i-1,i+2))
				res+="you",i++;
			else if(i+6<temp.size()&&temp.substr(i,7)=="can you"&&check(temp,i-1,i+7))
				res+="I can",i+=6;
			else if(i+8<temp.size()&&temp.substr(i,9)=="could you"&&check(temp,i-1,i+9))
				res+="I could",i+=8;
			else res+=temp[i];
		cout<<"AI: "<<res<<endl;
	}
	return 0;
}

这题挺锻炼对字符串处理的能力的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值