字符串处理
【PTA】估值一亿的AI核心代码
此题最开始的做法是将字符串以空格为分割拆成一个个子串(单词)来处理,拆分代码如下:
#include <iostream> // 引入输入输出流库
#include <sstream> // 引入字符串流库
#include <vector> // 引入向量库
#include <string> // 引入字符串库
int main() {
string input = "这是一个带空格 的字符串";
istringstream iss(input); // 将字符串转换为字符串流
vector<std::string> result; // 定义一个存储分割后的子字符串的向量
string temp; // 定义一个临时字符串用于存储分割后的子字符串
while (getline(iss, temp, ' ')) { // 使用getline函数以空格为分隔符分割字符串
result.push_back(temp); // 将分割后的子字符串添加到向量中
}
for (const auto &word : result) {
std::cout << word << std::endl;
}
return 0;
}
这样的处理虽然在输出时较为简便,但在 I 的转换上犯了难,即使经过多次修正,仍然无法AC,始终有一些小的点难以处理
于是,在之后发现对于这种不涉及单词顺序变化的问题中,将字符串拆成一个个单词的操作是有些多余的。可以写一个judge()函数,通过返回不同的数字来完成判断和分隔的作用,同时还需要更多字符串函数的协助,AC代码如下:
#include<bits/stdc++.h>
using namespace std;
int judge(char c){
if((c>='A' && c<='Z')||(c>='a' && c<='z')) return 1;
else if(c>='0' && c<='9') return 2;
else if(c==' ') return 0;
else return -1;
}//非字母和数字的返回值<=0,作为分隔的依据
string AI(string s){
while(s[0]==' ') s.erase(s.begin());
while(s[s.size()-1]==' ') s.erase(s.end()-1);
for(int i=0;i<s.size();i++){
if(s[i]>='A' && s[i]<='Z' && s[i]!='I'){
s[i]+=32;
}
if(s[i]=='?') s[i]='!';
if(s[i]==' '){
int j=i+1;
while(s[j]==' ') j++;
s.erase(s.begin()+i+1,s.begin()+j);
}
}
for(int i=0;i<s.size();i++){
if(i==0){
if(s[i]=='I' && (judge(s[i+1])<=0 || i+1==s.size())) s.replace(i,1,"you");
else if(s.substr(i,2)=="me" && (judge(s[i+2])<=0 || i+2==s.size())) s.replace(i,2,"you");
else if(s.substr(i,7)=="can you" && (judge(s[i+7])<=0 || i+7==s.size())) s.replace(i,7,"I can");
else if(s.substr(i,9)=="could you" && (judge(s[i+9])<=0 || i+9==s.size())) s.replace(i,9,"I could");
}
if(judge(s[i])<=0)
{
if(judge(s[i+1])==1)
{
if(s[i+1]=='I'&&(judge(s[i+2])<=0||i+2==s.size()))
s.replace(i+1,1,"you");
if(s.substr(i+1,2)=="me"&&(judge(s[i+3])<=0||i+3==s.size()))
s.replace(i+1,2,"you");
if(s.substr(i+1,7)=="can you"&&(judge(s[i+8])<=0||i+8==s.size()))
s.replace(i+1,7,"I can");
if(s.substr(i+1,9)=="could you"&&(judge(s[i+10])<=0||i+10==s.size()))
s.replace(i+1,9,"I could");
}
}
}
return s;
}
int main(){
int n;
string as,ss;
cin>>n;
getchar();
while(n--){
getline(cin,as);
cout<<as<<endl;
ss=AI(as);
cout<<"AI: ";
for(int i=0;i<ss.size();i++){
if(ss[i]==' ' && judge(ss[i+1])<=0) continue;
else cout<<ss[i];
}cout<<endl;
}
return 0;
}
字符串相关部分函数
字符判断
erase函数的三种使用方法:
(1)erase(pos,n); 删除从pos开始的n个字符,比如erase(0,1)就是删除第一个字符
(2)erase(position);删除position处的一个字符(position是个string类型的迭代器)
(3)erase(first,last);删除从first到last之间的字符(first和last都是迭代器)
replace() 函数用法:
(1)用str替换指定字符串从起始位置pos开始长度为len的字符
string& replace (size_t pos, size_t len, const string& str);
(2) 用str替换迭代器起始位置 和 结束位置 的字符
string& replace (const_iterator i1, const_iterator i2, const string& str);
(3)用substr的指定子串(给定起始位置和长度)替换从指定位置上的字符串
string& replace (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen);
(4)用重复n次的c字符替换从指定位置pos长度为len的内容
string& replace (size_t pos, size_t len, size_t n, char c);
(5) 用重复n次的c字符替换从指定迭代器位置(从i1开始到结束)内容
string& replace (const_iterator i1, const_iterator i2, size_t n, char c);
无向图,并查集,DFS
【PTA】排座位
最开始写的时候没想着用DFS,只向上都搜了一级,只有一个3分的点没过(感谢数据君
正经的还是要用DFS来进行查找,并且可以加一个bool函数来进行初步分类
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int e[105][105];
int par[105];
int GetBoss(int x){
if(x==par[x]) return x;
return GetBoss(par[x]);
}
void Merge(int x,int y){
int bossx=GetBoss(x);
int bossy=GetBoss(y);
par[bossx]=bossy;
}
bool Judge(int x,int y){
int bx=GetBoss(x);
int by=GetBoss(y);
return bx==by;
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
par[i]=i;
}
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
e[a][b]=c;
e[b][a]=c;
if(c==1){
Merge(a,b);
}
}
for(int i = 1;i <= k;i++)
{
int a, b;
cin >> a >> b;
if(Judge(a, b))
{
if(e[a][b] == 1)
cout << "No problem" << endl;
else if(e[a][b] == -1)
cout << "OK but..." << endl;
else if(e[a][b] == 0)
cout << "No problem" << endl;
}
else
{
if(e[a][b] == -1)
cout << "No way" << endl;
else
cout << "OK" << endl;
}
}
return 0;
}
【PTA】7-10 红色警报
本题也是一个无向图,每次一个城市被攻占后中使用DFS来统计联通块数量,以此来反应变化情况
#include<bits/stdc++.h>
using namespace std;
int maap[500][500];
int numap,temp[500];
void Dfs(int v,int num,int *flag){
flag[v]=1;
for(int i=0;i<num;i++){
if(maap[v][i]!=0 && flag[i]!=1){
Dfs(i,num,flag);
}
}
}
int Getmap(int num){
int numMap=0,flag[500];
for(int i=0;i<num;i++){
flag[i]=temp[i];
}
for(int i=0;i<num;i++){
if(flag[i]==0){
Dfs(i,num,flag);
numMap+=1;
}
}
return numMap;
}//若全国联通,dfs一次之后所有flag都为1,dfs只会进行一次,numMap==1
//若分隔成了不连通的两块,dfs就会进行两次,numMap==2;
int main(){
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++){
int x,y;
cin>>x>>y;
maap[x][y]=1;
maap[y][x]=1;
}
int numMap;
numMap=Getmap(n);
int num;
cin>>num;
for(int i=0;i<num;i++){
int v,k=-1;
cin>>v;
for(int j=0;j<n;j++){
if(maap[j][v]!=0) k=j;
maap[j][v]=0;
maap[v][j]=0;
}
temp[v]=1;
if(k==-1){
cout<<"City "<<v<<" is lost."<<endl;
numMap--;
continue;
}
int tempMap=Getmap(n);
if(tempMap==numMap) cout<<"City "<<v<<" is lost."<<endl;
else cout<<"Red Alert: City "<<v<<" is lost!"<<endl;
numMap=tempMap;
}
int tempMap=Getmap(n);
if(tempMap==0){
cout<<"Game Over."<<endl;
}
return 0;
}
总结
人际关系,地区通信,大多就是无向图
用形如map[a][b]=x; map[b][a]=y;这样来储存。
图中的联系大多即为下标与数据的联系,常用for(int i=1;i<=n;i++) map[i]=i; 这样的方式来初始化。