【Vijos1382】【BZOJ1398】寻找主人 Necklace

Description
这里写图片描述
给定两个项链的表示,判断他们是否可能是一条项链。
Input

输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的)。
Output

如果两条项链不可能同构,那么输出’No’,否则的话,第一行输出一个’Yes’,第二行输出该项链的字典序最小的表示。 设L = 项链长度, 对于50%的数据L <= 100000; 对于100%的数据L <= 1000000。
Sample Input

Sample Output

HINT

Source

yts大爷骗我QAQ跟我说用SAM做
然而您的AC代码只有3MB内存是什么意思…
然后我就做了然后就被卡内存了
BZOJ卡内存丧心病狂啊!!!Vijos不卡内存A了…

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 2000010
using namespace std;
char ch1[MAXN>>2],ch2[MAXN>2],s1[MAXN>>2],s2[MAXN>>2];
struct sam
{
    int last,cnt,p,np,q,nq;
    int len[MAXN],a[MAXN][10],fa[MAXN];
    sam()
    {
        last=++cnt;
    }
    void insert(int c)
    {
        p=last;last=np=++cnt;len[np]=len[p]+1;
        while (!a[p][c]&&p) a[p][c]=np,p=fa[p];
        if (!p) fa[np]=1;
        else
        {
            q=a[p][c];
            if (len[q]==len[p]+1)   fa[np]=q;
            else
            {
                nq=++cnt;len[nq]=len[p]+1;
                memcpy(a[nq],a[q],sizeof(a[q]));
                fa[nq]=fa[q];fa[q]=fa[np]=nq;
                while (a[p][c]==q)  a[p][c]=nq,p=fa[p];
            }
        }
    }
}sam;
int main()
{
    scanf("%s",ch1+1);int n=strlen(ch1+1);
    for (int T=1;T<=2;T++)
        for (int i=1;i<=n;i++)  sam.insert(ch1[i]-'0');
    int st=1;
    for (int i=1;i<=n;i++)
        for (int j=0;j<=9;j++)
            if (sam.a[st][j])   {st=sam.a[st][j];s1[i]=j+'0';break;}
    st=1;sam.last=sam.cnt=1;scanf("%s",ch1+1);
    memset(sam.a,0,sizeof(sam.a));memset(sam.fa,0,sizeof(sam.fa));memset(sam.len,0,sizeof(sam.len));
    for (int T=1;T<=2;T++)
        for (int i=1;i<=n;i++)  sam.insert(ch1[i]-'0');
    for (int i=1;i<=n;i++)
        for (int j=0;j<=9;j++)
            if (sam.a[st][j])   {st=sam.a[st][j];s2[i]=j+'0';break;}
    for (int i=1;i<=n;i++)
        if (s1[i]!=s2[i])   {puts("No");return 0;}
    puts("Yes");
    for (int i=1;i<=n;i++)  putchar(s1[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值