B. Ugly Pairs

52 篇文章 1 订阅
8 篇文章 0 订阅

https://codeforces.com/problemset/problem/1156/B

题目描述

You are given a string, consisting of lowercase Latin letters.

A pair of neighbouring letters in a string is considered ugly if these letters are also neighbouring in a alphabet. For example, string "abaca" contains ugly pairs at positions (1, 2)(1,2) — "ab" and (2, 3)(2,3) — "ba". Letters 'a' and 'z' aren't considered neighbouring in a alphabet.

Can you rearrange the letters of a given string so that there are no ugly pairs? You can choose any order of the letters of the given string but you can't add any new letters or remove the existing ones. You can also leave the order the same.

If there are multiple answers, print any of them.

You also have to answer TT separate queries.

输入格式

The first line contains a single integer TT ( 1 \le T \le 1001≤T≤100 ) — the number of queries.

Each of the next TT lines contains string ss (1 \le |s| \le 100)(1≤∣s∣≤100) — the string for the next query. It is guaranteed that it contains only lowercase Latin letters.

Note that in hacks you have to set T = 1T=1 .

输出格式

Print TT lines. The ii -th line should contain the answer to the ii -th query.

If the answer for the ii -th query exists, then print such a rearrangment of letters of the given string that it contains no ugly pairs. You can choose any order of the letters of the given string but you can't add any new letters or remove the existing ones. You can also leave the order the same.

If there are multiple answers, print any of them.

Otherwise print "No answer" for that query.

题意翻译

题意

你有一个字符串,请将这个字符串进行排序,使得字符串中相邻的字母在字母表中不相邻(a 与 z 也不相邻)

输入

共 t(t≤100) 组数据,每一个数据包含一个长度不超过 100 的字符串

输出

对于每一组数据,如果可以完成任务,输出任意一个排序后的字符串;如果无法完成任务,请输出 No answer

输入输出样例

输入 #1复制

4
abcd
gg
codeforces
abaca

输出 #1复制

cadb
gg
codfoerces
No answer

说明/提示

In the first example answer "bdac" is also correct.

The second example showcases the fact that only neighbouring in alphabet letters are not allowed. The same letter is ok.

There are lots of valid answers for the third example.


思路:这道题拿到的时候感觉思路很多,但是有的不保证正确性,有的太麻烦了。比如想到暴力搜索check,比较麻烦。比如想到贪心思路,找一个字符然后找离他最近的满足的放进去,反复check。或者模拟把不满足的移到后面去什么的。有的hack了自己。想到了和奇偶性有关但是不知道具体什么情况,感觉是a,c...一串和b,d,..一串去构造。(当然看了官方题解之后这样确实是对的)

这里采用双端队列模拟,先把字符串sort,令相同的字符凑到一块。

然后把一个字符放到deque里,再在字符串里面反复找未曾访问并且和队头队尾不冲突的放进去,如果出现了没法放的情况就无解了。

因为开始模拟的时候担心第一个放哪个是有影响,所以如果不放心的话总共也就26个字母,在出现过的字母中枚举一下每个作为第一个入deque的情况也可以。当然最后ac的就直接放第一个字母就好了。

至于放一个就好的原因我猜是双端队列队头/队尾放的时候出现了其他字母第一个入deque的状态...(雾

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5;
typedef long long LL;
bool vis[130];
void solve()
{
	memset(vis,0,sizeof(vis));
	string s;cin>>s;
	sort(s.begin(),s.end());
	deque<char>a;
	a.push_back(s[0]);
    vis[0]=true;
	while(1)
    {
    	bool flag=1;
		for(LL i=0;i<s.size();i++)
		{
			if(!vis[i])
			{
				char head=a.front();//队头能否插入
				char tail=a.back();//队尾能否插入 
				
				if( abs(head-s[i] )>=2||head==s[i])
				{
					a.push_front(s[i]);vis[i]=true;flag=0;	
				} 
				else if(abs( tail-s[i] )>=2||tail==s[i])
				{
					a.push_back(s[i]);vis[i]=true;flag=0;
				} 
			}
		}
		if(a.size()==s.size()){
			for(LL i=0;i<a.size();i++) cout<<a[i];
			cout<<endl;		
			return;
		}
		if(flag){
			cout<<"No answer"<<endl;return;
		}
	}
}
int main(void)
{
  LL t;cin>>t;
  while(t--)
  {
  	 solve();	
  }
return 0;
}

附上奇偶性的答案:https://codeforces.com/blog/entry/66827

代码源于洛谷题解:

// =================================
//   author: M_sea
//   website: http://m-sea-blog.com/
// =================================
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define re register
using namespace std;
 
inline int read() {
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') c=getchar();
    while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
    return X*w;
}
 
const int N=100+10;
 
int n,sa,sb;
char s[N],a[N],b[N];
 
int main() {
    int T=read();
    while (T--) {
        scanf("%s",s+1); n=strlen(s+1),sa=sb=0;
        for (re int i=1;i<=n;++i) {
            if (s[i]&1) a[++sa]=s[i];
            else b[++sb]=s[i];
        }
        sort(a+1,a+sa+1),sort(b+1,b+sb+1);
        if (abs(b[1]-a[sa])!=1) {
            for (re int i=1;i<=sa;++i) putchar(a[i]);
            for (re int i=1;i<=sb;++i) putchar(b[i]);
            puts("");
        }
        else if (abs(a[1]-b[sb])!=1) {
            for (re int i=1;i<=sb;++i) putchar(b[i]);
            for (re int i=1;i<=sa;++i) putchar(a[i]);
            puts("");
        }
        else puts("No answer");
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值