1. 程式人生 > >計蒜客 字串條件

計蒜客 字串條件

通過 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; };