Codeforces 1303C Perfect Keyboard

给你一个字符串,要求你设计一种键盘,这个键盘用一行表示,其中在题目字符串中相邻的字符,在你的键盘上也要相邻。

我们用三个数组模拟一个双向链表,pre[i]表示i字符前一个字符,nxt[i]表示i字符后一个字符,vis[i]标记i字符是否在链表中出现。

输出的时候我们先把链表输出,再把剩余的随便输出就i行。

一个字符在链表出现过后,它的位置就是固定了的,如果前后为空可以添加,但不能使它调到别的地方。不能出现循环链表。

因为输出的一行,某两个相邻的一定会被拆到链表两头,就不相邻了。

具体细节在代码注释里。

注意特判输入只有一个字符的情况。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=205;
char s[N];
int pre[31],nxt[31],vis[31];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
       cin>>s;
       for(int i=0;i<26;i++) pre[i]=nxt[i]=-1,vis[i]=0;//初始化,-1代表前后没有字符,0代表没有出现过
       int l=strlen(s),flag=1;
       if(l==1) 
       {
           printf("YES\n");
           for(int i=0;i<26;i++) printf("%c",i+'a');
           printf("\n");
           continue;
       }
       vis[s[0]-'a']=1;//先把第一个字符标记上
       for(int i=1;i<l&&flag;i++)//从第二个字符开始,防止越界
       {
           int pree=s[i-1]-'a',tmp=s[i]-'a';//tmp表示当前字符,pree表示当前字符在输入中的前一个字符
           if(pre[pree]==tmp||nxt[pree]==tmp) continue;//满足题目要求,不需要再进行了
           flag=0;//标记字符是否成功放进链表
           if(vis[tmp]) break;//pree一定已经在链表中了,此时tmp也在链表中
//一种情况tmp两端都有元素,上面已经判断过,两端是pree的已经continue了,到这里说明不是
//一种情况tmp一端有元素,另一端为空,如果让空的这端与pree相连,就成循环了
//链表中不可能两端都没有元素
           if(nxt[pree]==-1)//tmp加在pree后面
           {
               nxt[pree]=tmp;
               pre[tmp]=pree;
               flag=1;
           } 
           if(flag==0&&pre[pree]==-1)//tmp加在pre前面
           {
               pre[pree]=tmp;
               nxt[tmp]=pree;
               flag=1;
           } 
           if(flag==1) vis[tmp]=1;//添加成功,标记在链表中出现了
       }
       if(flag==0) cout<<"NO"<<endl;//有节点添加不进去
       else
       {
            cout<<"YES"<<endl;
            for(int i=0;i<26;i++)
            {
                if(pre[i]==-1&&nxt[i]!=-1)//找到链表头
                {
                    int x=i;
                    while(x!=-1) //输出链表
                    {
                        printf("%c",x+'a');
                        x=nxt[x];
                    }
                    break;
                }
            }
            for(int i=0;i<26;i++) if(!vis[i]) printf("%c",i+'a');
            cout<<endl;
       }
    }
    //system("pause");
}

猜你喜欢

转载自blog.csdn.net/Luowaterbi/article/details/104298629