计蒜客 字符串条件

版权声明:原来这里可以拿来卖萌ヽ(・∀・)ノ https://blog.csdn.net/u012345506/article/details/78872006

通过 O(n) 处理next数组,可以得到一些诸如 Si=Sj SiSj 的式子,将所有相等的位置都连通起来。之后为所有不等号连边,问题变成用16个颜色在这个图上染色,且点编号越小,颜色值越小。 O(n) 贪心即可。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))
//--Container
#include<vector>
//
typedef long long ll;
typedef unsigned long long ull;

struct eg{int u,v,nx;}gp[200010];
int ar[100010],ct[100010],bi[100010][2],hd[100010],rs[100010],cnt,bn,sm,n;char cz[100010];
int fi(int a){return ct[a]==a?a:ct[a]=fi(ct[a]);};
void psh(int u,int v){++cnt;gp[cnt].u=u,gp[cnt].v=v,gp[cnt].nx=hd[u],hd[u]=cnt;};

bool _cl(){
    int i,j;bool bd[16];if(ar[1])return 0;
    if(n==1){cz[1]='a';return 1;}
    for(i=1;i<=n;++i)ct[i]=i;
    for(bn=0,i=2;i<=n;++i){
        for(j=ar[i-1];j&&j+1!=ar[i];j=ar[j]){bi[bn][0]=j+1,bi[bn][1]=i;++bn;}
        if(!ar[i]){bi[bn][0]=1,bi[bn][1]=i;++bn;continue;}
        if(ar[i]!=j+1)return 0;
        ct[i]=fi(j+1);
    }
    for(cnt=0,clr(hd),i=0;i<bn;++i){
        bi[i][0]=fi(bi[i][0]),bi[i][1]=fi(bi[i][1]);
        if(bi[i][0]==bi[i][1])return 0;
        psh(bi[i][0],bi[i][1]),psh(bi[i][1],bi[i][0]);
    }
    for(clr(rs),i=1;i<=n;++i){
        for(clr(bd),j=hd[i];j;j=gp[j].nx)bd[rs[gp[j].v]]=1;
        for(j=1;j<=16&&bd[j];++j);
        if(j>16)return 0;
        rs[i]=j;
    }
    for(i=1;i<=n;++i)cz[i]=rs[fi(i)]+'a'-1;
    return 1;
};

void cl(){
    int i,j,k,t,a,b;scanf("%d",&n);
    for(clr(cz),clr(ar),i=1;i<=n;scanf("%d",&ar[i++]));
    if(!_cl())printf("-1\n");
    else
        printf("%s\n",cz+1);
};

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    cl();
    return 0;
};

猜你喜欢

转载自blog.csdn.net/u012345506/article/details/78872006