Description
给定两个串 (S,T),判断它们是否循环同构,如果是则输出它的最小循环表示。
Solution
考虑把两个串的最小循环表示都算出来,然后判断它们是否相等
把串翻倍建 SAM,然后贪心地走最小转移边 (len) 次即可
(强行缩了一些内存结果居然混过去了
#include <bits/stdc++.h>
using namespace std;
const int Maxn = 4000005;
#define reset(x) memset(x,0,sizeof x)
struct Suffix_Automata
{
int maxlen[Maxn], trans[Maxn][10], link[Maxn], Size, Last;
void clear()
{
reset(maxlen);
reset(trans);
reset(link);
Size = Last = 1;
}
Suffix_Automata()
{
clear();
}
inline void extend(int id)
{
int cur = (++ Size), p;
maxlen[cur] = maxlen[Last] + 1;
for (p = Last; p && !trans[p][id]; p = link[p]) trans[p][id] = cur;
if (!p) link[cur] = 1;
else
{
int q = trans[p][id];
if (maxlen[q] == maxlen[p] + 1) link[cur] = q;
else
{
int clone = (++ Size);
maxlen[clone] = maxlen[p] + 1;
for(int i=0; i<10; i++) trans[clone][i] = trans[q][i];
link[clone] = link[q];
for (; p && trans[p][id] == q; p = link[p]) trans[p][id] = clone;
link[cur] = link[q] = clone;
}
}
Last = cur;
}
string solve(int n)
{
int p=1;
string res;
for(int i=0; i<n; i++)
{
for(int j=0; j<10; j++)
{
if(trans[p][j])
{
res+='0'+j;
p=trans[p][j];
break;
}
}
}
return res;
}
} sam;
int main()
{
ios::sync_with_stdio(false);
string str;
int n;
string r[2];
for(int i=0; i<2; i++)
{
sam.clear();
cin>>str;
n=str.length();
for(int j=0; j<n; j++) sam.extend(str[j]-'0');
for(int j=0; j<n; j++) sam.extend(str[j]-'0');
r[i]=sam.solve(n);
}
if(r[0]==r[1])
{
cout<<"Yes"<<endl;
cout<<r[0]<<endl;
}
else
{
cout<<"No"<<endl;
}
}