#C231109A. 万能遥控器


#C231109A. 万能遥控器

前言(Front talk)

$\qquad$这是一道大美女(bushi)

da’mo’ni

$\qquad$好像是首次打这种类似的模拟题,还是挺激动的。( •̀ ω •́ )✧

网址(Website)

题目详情 - 万能遥控器 - Super

题解 - 万能遥控器 - Super

题解(Solution)

几个注意点:

  • $For(i,l,r)$ 里面不要加 $s.length()$ ,一定要换成定值 $len$ ,否则要出错。(是答案出错而不是报错,会凭空花费很多时间)
  • 要去除非 $16$ 进制的字符
  • 区间字符数不能大于 4 个
  • 首个或结尾出现的单个冒号,不合法
  • 没有 :: 作省略却不足 8 个 地址
  • 一个单独的0分组不能使用 :: 省略
  • 地址多于 8 个
  • 省略的 0 需补全
  • 结尾冒号省略
  • 多测清空

代码(Code)

#include<bits/stdc++.h>
#include<vector>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
using namespace std;
inline int input(){int x;return cin>>x,x;}
const int mao=8;
int n;
string s;
vector<char> jian[14];//区间 
int tot;//记录区间个数 
int rem;//记录双冒号的位置 
void solve(string s){
	//初始化 
	For(i,1,8) jian[i].clear();
	rem=-1;tot=0;
	int len=s.length();
	//去除非 16 进制的字符 
	For(i,0,len-1){
		if(!isdigit(s[i]) && (s[i]!=':' && s[i]!='A' && s[i]!='B' && s[i]!='C' && s[i]!='D' && s[i]!='E' && s[i]!='F')){
			return cout<<"INVALID\n",void();
		}
	} 
	//找到 :: 的位置 
	For(i,0,len-2){
		if(s[i]==s[i+1] && s[i]==':'){
			if(rem!=-1) return cout<<"INVALID\n",void();//出现了多个 :: 或者出现了 ::: 
			rem=i;
		}
	}
	//每个区间
	for(int i=0;i<len;){
		while(i<len && s[i]==':') i++;
		if(i>=len) break;//:: 冒号后的区间可能为空,舍去 
		tot++;//开新的区间 
		while(i<len && s[i]!=':'){
			jian[tot].emplace_back(s[i]);
			i++;
		}if(jian[tot].size()>4) return cout<<"INVALID\n",void();//区间字符数大于 4 个 
	}
	//特判首个或结尾出现的单个冒号,不合法 
	if(s[0]==':' && rem!=0) return cout<<"INVALID\n",void();
	if(s[len-1]==':' && rem!=len-2) return cout<<"INVALID\n",void();
	//没有 :: 作省略却不足 8 个 地址 
	if(rem==-1 && tot!=8) return cout<<"INVALID\n",void();
	//一个单独的0分组不能使用 :: 省略 
	if(rem>=0 && 8-tot<=1) return cout<<"INVALID\n",void();
	//地址多于 8 个 
	if(tot > 8) return cout<<"INVALID\n",void();
	//输出
	for(int i=0,k=1;i<len;){
		if(i==rem){//如果是 :: 
			For(k,1,8-tot){
				if(i+2==len && k==8-tot) cout<<"0000";//结尾冒号省略 
				else cout<<"0000:";
			}i+=2;continue;
		}while(i<len && s[i]==':') i++;//跳过 : 
		
		For(ss,1,4-jian[k].size()) cout<<'0';//省略的 0 需补全 
		for(auto c:jian[k]){
			cout<<c;
			i++;
		}if(i<len)cout<<":";//结尾冒号省略
		k++;//下一个区间 
	}cout<<'\n';return;
}

signed main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	string str("ipv6");
	freopen((str+".in").c_str(),"r",stdin);
	freopen((str+".out").c_str(),"w",stdout);
	cin>>n;while(n--){
		cin>>s;
		solve(s);
	}return 0;
}

后续(Ending)

本来准备放题解代码的,结果发现题解代码比我的还丑。`(>﹏<)′


文章作者: WolfDeer
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WolfDeer !
  目录