SMU_ACM 3.25.2024——3.31.2024

字符串处理

【PTA】估值一亿的AI核心代码

PTA | 程序设计类实验辅助教学平台

此题最开始的做法是将字符串以空格为分割拆成一个个子串(单词)来处理,拆分代码如下:

#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】排座位

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 红色警报

PTA | 程序设计类实验辅助教学平台

本题也是一个无向图,每次一个城市被攻占后中使用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; 这样的方式来初始化。

  • 31
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值