SCOI2013 密码

题目描述:

Fish是一条生活在海里的鱼。有一天他很无聊,就到处去寻宝。他找到了位于海底深处的宫殿,但是一扇带有密码锁的大门却阻止了他的前进。

通过翻阅古籍,Fish 得知了这个密码的相关信息:

  1. 该密码的长度为N。

  2. 密码仅含小写字母。

  3. 以每一个字符为中心的最长回文串长度。

  4. 以每两个相邻字符的间隙为中心的最长回文串长度。

很快Fish 发现可能有无数种满足条件的密码。经过分析,他觉得这些密码中字典序最小的一个最有可能是答案,你能帮他找到这个密码么?

注意:对于两个串A和B,如果它们的前i个字符都相同,而A的第i+1个字符比B的第i+1个字符小,那么认为是则称密码A 的字典序小于密码B 的字典序,例如字符串abc 字典序小于字符串acb。如果密码A的字典序比其他所有满足条件的密码的字典序都小,则密码A是这些密码中字典序最小的一个。

 题解:
manacher反演?

贪心+并查集,判断这一位上字符的时候只需要与前边的1个点制造联系。

和manacher好像啊。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100050
inline int rd()
{
    int f=1,c=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
    return f*c;
}
int n,p[2*N];
int hed[2*N],cnt;
struct EG
{
    int to,nxt;
}e[4*N];
void ae(int f,int t)
{
    e[++cnt].to = t;
    e[cnt].nxt = hed[f];
    hed[f] = cnt;
}
int col[2*N],fa[2*N];
bool vis[28];
int findfa(int x)
{
    if(x==fa[x])return x;
    return fa[x]=findfa(fa[x]);
}
int main()
{
    n=rd();
    for(int i=2;i<=2*n;i+=2)
        p[i]=rd();
    for(int i=3;i<=2*n-1;i+=2)
        p[i]=rd();
    for(int i=2;i<=2*n;i++)
        fa[i]=i;
    int mx = 0;
    for(int i=2;i<=2*n;i++)
    {
        for(int j=max(i&1,mx-i+(i&1));j<=p[i];j+=2)
        {
            int f1 = findfa(i-j),f2 = findfa(i+j);
            if(f1!=f2)fa[f2]=f1;
        }
        mx = max(mx,i+p[i]-(i&1));
    }
    for(int i=2;i<=2*n;i++)
    {
        int f1 = findfa(i-p[i]-1);
        int f2 = findfa(i+p[i]+1);
        ae(f2,f1);ae(f1,f2);
    }
    mx=0;
    for(int i=2;i<=2*n;i+=2)
    {
        int ff = findfa(i);
        if(!col[ff])
        {
            for(int j=1;j<=26;j++)vis[j]=0;
            for(int j=hed[ff];j;j=e[j].nxt)
                vis[col[e[j].to]]=1;
            for(int j=1;j<=26&&!col[ff];j++)
                if(!vis[j])col[ff]=j;
        }
        printf("%c",col[ff]+'a'-1);
        if(i+p[i]-1>mx)
        {
            for(int j=mx+2;j<=i+p[i]-1;j+=2)
                col[j]=col[i*2-j];
            mx=i+p[i]-1;
        }
    }
    printf("\n");
    return 0;
}

 

posted @ 2018-11-30 19:59  LiGuanlin  阅读(230)  评论(0编辑  收藏  举报