L1-064 估值一亿的ai核心代码 (分数20)字符串处理

张开发
2026/4/4 4:18:03 15 分钟阅读
L1-064 估值一亿的ai核心代码 (分数20)字符串处理
•无论用户说什么首先把对方说的话在一行中原样打印出来•消除原文中多余空格把相邻单词间的多个空格换成 1 个空格把行首尾的空格全部删掉把标点符号前面的空格删掉•把原文中所有大写英文字母变成小写除了 I•把原文中所有独立的 can you、could you 对应地换成 I can、I could—— 这里“独立”是指被空格或标点符号分隔开的单词•把原文中所有独立的 I 和 me 换成 you•把原文中所有的问号 ? 换成惊叹号 !•在一行中输出替换后的句子作为 AI 的回答。现在请你模拟手搓一个能满足这些功能代码来模拟ai。我来模拟ai真的假的输入格式输入首先在第一行给出不超过 10 的正整数 N随后 N 行每行给出一句不超过 1000 个字符的、以回车结尾的用户的对话对话为非空字符串仅包括字母、数字、空格、可见的半角标点符号。输出格式按题面要求输出每个 AI 的回答前要加上 AI: 和一个空格。解题思路算法一朴素做法我先要介绍一种处理字符串中单词之间多个空格的方法我们可以像之前L1-049那样用一个last来记录上一个字符是啥状态 \比如bool last_is_space true; 再利用isalnumchar函数完成对输入字符串的整理记整理后的字符串为clean由于这里需要先输出原句所以肯定需要使用getline不能用cin自动跳过不可见字符遍历字符串的过程中我们需要分三种情况讨论1. 单词包含数字和字母 2. 空格 3. 标点符号 ;●如果该字符是 单词 就直接放进clean字符串●如果是空格检查last_is_space如果是false就放进clean并改变状态●如果是标点符号要检查last_is_space和clean.size() 因为要去掉标点符号前的空格但是标点符号可能出现在字符串第一个而刚开始last_is_space 的状态就是true所以还要检查clean.size()任何访问容器元素的操作都要判断是否为空或者可以检查clean.size() clean.back()如果有空格就pop.back()后者更符直觉前者符合前面的代码设计注意常见的容器 如vector 和 string 都有 front和 back 之前我也不知道这个o(╥﹏╥)o然后把整个字符串clean之后就是对单词大小写为了方便可以在clean的过程中转换为小写特定词的替换问号进行处理。ac代码✅️#includeiostream#includestring#includevector#includecctypeusing namespace std;bool isSymbol(char c){return !isalnum(c);}int main(){int n;cinn;cin.ignore();while(n--){string s;getline(cin,s);coutsendl;string clean;bool lastIsSpace true;for(int i 0 ; i s.size() ; i){char c s[i];if(c ){if(!lastIsSpace){clean ;lastIsSpace true;}}else if( isSymbol(c) ){//这里提个问题为啥 “只” 要检查 “末尾” 是否是空格 前面不可能有空格吗if(lastIsSpace clean.size()) clean.pop_back();if(c ?) c !;clean c;lastIsSpace false;}else{if(c ! I) c tolower(c);clean c;lastIsSpace false;}}if(clean.size() 0 clean.back() ) clean.pop_back();vectorstring tokens;string temp ;for(int i 0 ; i clean.size() ; i){if(isalnum(clean[i])) temp clean[i];else{if(temp ! ){//这里的作用是把每个单词放进tokens便于单词替换//遇到空格或者标点符号说明放完一个单词了//接下来要清空temp便于下一个单词的放入tokens.push_back(temp);temp ;}//char要转换为string才能放入string sym(1,clean[i]);tokens.push_back(sym);}}//clean的行末可能有空格可能没有如果没有会有一个temp没被加//需要在循坏结束后特判一下if(temp ! ) tokens.push_back(temp);for(int i 0 ; i tokens.size() ; i){string now tokens[i];if(now can i 2 tokens.size() tokens[i1] tokens[i2] you){tokens[i] I;tokens[i2] can;i2;}else if(now could i 2 tokens.size() tokens[i1] tokens[i2] you){tokens[i] I;tokens[i2] could;i 2;}else if(now I) tokens[i] you;else if(now me) tokens[i] you;}coutAI: ;for(const string t : tokens) coutt;coutendl;}return 0;}还没完还有一种牛逼轰轰的写法(后续我发现并没有)用到了s.find_first_not_of( ) 和 s.find_last_not_of( ) 分别可以找到字符串第一个不为空格的下标和最后一个不为空格的下标完美地控制了主体部分的范围。然后遍历主体如果s[i] 和 s[i1] 都是空格就可以continue保证只加入了一个空格其实这里可以在clean的过程中 改变大小写和问号换感叹号等等只需要考虑单词替换的问题。这里用到了正则表达式 。这里只介绍regex的replace函数单词替换#includeiostream#includeregexusing namespace std;int main(){string s I love you,can you love me?;s regex_replace(s , regex(\\bcan you\\b), I can);coutsendl;return 0;}clean过程s regex_replace(s, regex(^ | $), ); // 删去首尾空格s regex_replace(s, regex( ), ); // 多空格压成单空格s regex_replace(s, regex( ([^a-zA-Z0-9 ])), $1); // 删去标点前的空格 (匹配非字母数字空格)解释说明\b表示边界也可以说是与其他词的边界在上述演示中\b严格限制了替换的内容它与find不同的是如果字符串中有oldcan youschool,find会找到can you并替换而regex_replace找不到它只能找到独立的can you。regex(^ | $)在该函数中起到了搜索的作用 ^表示从开头开始匹配, 接下来的 “ ” 表示匹配开头的多个空格|表示或 即左右两种匹配搜索方式都可以 ,$$表示 结尾 , “ $”表示匹配结尾前面的多个空格实现了去除字符串开头或结尾的多余空格regex( ([^a-zA-Z0-9 ]))表示匹配([^a-zA-Z0-9 ])前面的多个空格[]表示指定一个字符集其内容为^a-zA-Z0-9 这里有个空格请注意)^为反的意思a-zA-Z0-9 就是字符串中不是字母也不是数字还不是空格的字符在题目限制下就是标点符号逗号感叹号等等将标点符号和前面的空格全部换成标点符号$1表示[]匹配到的内容这里就是标点符号。ac代码✅️✅️#include iostream#include string#include regex#include cctypeusing namespace std;void solve(){string s;getline(cin, s);cout s endl; // 第一步原样输出// 1. 朴素版大小写转换与问号替换 (这一步必须手动最快最稳)for (int i 0; i s.size(); i){if (s[i] A s[i] Z s[i] ! I){s[i] tolower(s[i]);}else if (s[i] ?){s[i] !;}}// 2. 正则版清理空格 (顺序千万不能乱)s regex_replace(s, regex(^ | $), ); // 删去首尾空格s regex_replace(s, regex( ), ); // 多空格压成单空格s regex_replace(s, regex( ([^a-zA-Z0-9 ])), $1); // 删去标点前的空格 (匹配非字母数字空格)// 3. 正则版单词替换 (利用大写 A 作为绝妙占位符)s regex_replace(s, regex(\\bcan you\\b), A can);s regex_replace(s, regex(\\bcould you\\b), A could);s regex_replace(s, regex(\\bI\\b), you);s regex_replace(s, regex(\\bme\\b), you);s regex_replace(s, regex(\\bA\\b), I); // 最后把 A 变回 Icout AI: s endl;}int main(){int n;if (cin n){cin.ignore();while (n--){solve();}}return 0;}

更多文章