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]);
}