(Nowcoder) B.Shorten IPv6 Address

传送门

解:就是个模拟了,唯一要注意的删除同样的0,删除中间的使得结果更短,因为多删除一个:号。

比赛写的代码就比较臭了。


#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d %d",&n,&m)
#define SZ(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define drep(i,a,b)	for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const double pi=acos(-1.0);
const double eps=1e-9;
void cg(const char *sSrc,  char *sDest, int nSrcLen) {
	int times=nSrcLen/4;
	char temp[times];
	int x=0;
	for(int i=0; i<times; i++) {
		x=8*(sSrc[i*4]-'0');
		x+=4*(sSrc[i*4+1]-'0');
		x+=2*(sSrc[i*4+2]-'0');
		x+=sSrc[i*4+3]-'0';
		sprintf(temp+i,"%1x",x);
	}
	memcpy(sDest,temp,times);
}
char b[500],a[2000];
int T,id=0;
struct node {
	int st,num,ls;
};
bool cmp(node x,node y) {
	if(x.num!=y.num) return x.num>y.num;
	else return x.st>y.st;
}
vector<node> tt;
int main() {
	sc(T);
	while(T--) {
		scanf("%s",a);
		cg(a,b,strlen(a));
		string ans="";
		int cnt=0;
		bool fg=0;
		for(int i=0; i<32; i+=4) {
			fg=0;
			for(int j=i; j<i+4; ++j) {
				if(b[j]!='0' && !fg) {
					fg=1;
					ans+=b[j];
				} 
				else if(fg) ans+=b[j];
			}
			if(!fg) ans+='0',cnt++;
			if(i<28)ans+=':';
		}
		//	cout<<ans<<endl;
		cout<<"Case #"<<(++id)<<": ";
		if(cnt==8) cout<<"::"<<endl;
		else {
			tt.clear();
			int nst=-1,tot=0,ls;
			for(int i=0; i<SZ(ans);) {
				if(ans[i]=='0' && (i==0 || ans[i-1]==':')) {
					if(i==0) nst=i;
					else nst=i-1;
					tot=0;
					int j;
					for(j=i; j<SZ(ans); ++j) {
						if(ans[j]=='0') tot++;
						if(ans[j]!='0' && ans[j]!=':') break;
					}
					if(tot>=2) tt.pb(node {nst,j-nst,j});
					i=j;
				} 
				else ++i;
			}
			if(SZ(tt)==0) {
				cout<<ans<<endl;
			} 
			else {
				sort(tt.begin(),tt.end(),cmp);
				node tp=tt[0];
			    //cout<<"erase "<<tp.st<<" "<<tp.ls<<endl;
				ans.erase(ans.begin()+tp.st,ans.begin()+tp.ls);
				ans.insert(tp.st,"::");
				cout<<ans<<endl;
			}

		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值