这道题目自己傻傻的写拓扑排序写错了,直接写成了,细节MAX
这里在贴一个别人的好代码
Mine:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=500010,Max_SG=26;
char str[N],ansA[N],ansB[N];
int lena,lenb;
struct SAM{
int last,root,cnt,tim;
int fa[N],c[N][26],len[N],SG[N],q[N],in[N];
LL dp[N][27],sum[N];
bool vis[N];
void init()
{last=root=++cnt;}
void extend(int x)
{
int p=last,np=last=++cnt;
len[np]=len[p]+1;
while (p && !c[p][x])
c[p][x]=np,p=fa[p];
if (!p) fa[np]=root;
else
{
int q=c[p][x];
if (len[q]==len[p]+1)
fa[np]=q;
else
{
int nq=++cnt;
len[nq]=len[p]+1;
memcpy(c[nq],c[q],sizeof(c[q]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
while (p && c[p][x]==q)
c[p][x]=nq,p=fa[p];
}
}
}
void insert(char *str)
{
init();
int len=strlen(str);
for (int i=0;i<len;i++)
extend(str[i]-'a');
}
void calc_SG_dp()
{
int l=1,r=1;
for (int i=1;i<=cnt;i++)
for (int j=0;j<26;j++)
if (c[i][j]) in[c[i][j]]++;
for (int i=1;i<=cnt;i++)
if (!in[i]) q[r++]=i;
while (l<r)
{
int u=q[l++];
for (int i=0;i<26;i++)
{
int v=c[u][i];
if (!v) continue;
in[v]--;
if (!in[v]) q[r++]=v;
}
}
for (int i=cnt;i>=1;i--)
{
int u=q[i];
for (int j=0;j<=Max_SG;j++) vis[j]=false;
for (int j=0;j<26;j++)
if (c[u][j]) vis[SG[c[u][j]]]=true;
SG[u]=0;
while (vis[SG[u]]) SG[u]++;
}
for (int i=cnt;i>=1;i--)
{
int u=q[i];
dp[u][SG[u]]=1;
for (int j=0;j<26;j++)
{
if (!c[u][j]) continue;
int v=c[u][j];
for (int k=0;k<=Max_SG;k++)
dp[u][k]+=dp[v][k];
}
for (int k=0;k<=Max_SG;k++) sum[u]+=dp[u][k];
}
}
}A,B;
void solve(LL K)
{
lena=lenb=0;
int nowa=1,nowb=1;
while (true)
{
bool flag=true;
int sg=A.SG[nowa];
LL tmp=B.sum[1]-B.dp[1][sg];
if (tmp>=K) break;
K-=tmp;
for (int i=0;i<26;i++)
{
if (!A.c[nowa][i]) continue;
int u=A.c[nowa][i];
LL tmp=0;
for (int j=0;j<=Max_SG;j++)
tmp+=(B.sum[1]-B.dp[1][j])*A.dp[u][j];
if (tmp<K) K-=tmp;
else
{
nowa=u;
flag=false;
ansA[lena++]=i+'a';
break;
}
}
if (flag) {puts("NO");return;}
}
for (int i=0;i<lena;i++) putchar(ansA[i]); puts("");
int sg=A.SG[nowa];
while (K>0)
{
int sgB=B.SG[nowb];
if (sgB!=sg) K--;
if (!K) break;
for (int i=0;i<26;i++)
{
int v=B.c[nowb][i];
if (!v) continue;
LL tmp=B.sum[v]-B.dp[v][sg];
if (tmp<K) K-=tmp;
else
{
nowb=v;
ansB[lenb++]=i+'a';
break;
}
}
}
for (int i=0;i<lenb;i++) putchar(ansB[i]); puts("");
}
int main()
{
LL K;
scanf("%lld",&K);
scanf("%s",str);
A.insert(str);
A.calc_SG_dp();
scanf("%s",str);
B.insert(str);
B.calc_SG_dp();
solve(K);
return 0;
}
and good:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 100005
#define N 200005
#define LL long long
using namespace std;
struct SAM{
int n,ch[N][26],sg[N],fr[N],len[N],tot;
LL cnt[N][28];
char S[M];
void NewNode(int &p,int d,int pl,int f){
p=++tot;
len[p]=d,fr[p]=f;
if(pl==-1)for(int i=0;i<26;i++)ch[p][i]=-1;
else for(int i=0;i<26;i++)ch[p][i]=ch[pl][i];
}
void Addchar(int u,int &p,int c){
NewNode(p,len[u]+1,-1,-1);
int v=u;
while(v!=-1&&ch[v][c]==-1){
ch[v][c]=p;
v=fr[v];
}
if(v==-1){
fr[p]=0;
return;
}
int x=ch[v][c],y;
if(len[x]==len[v]+1){
fr[p]=x;
return;
}
NewNode(y,len[v]+1,x,fr[x]);
fr[x]=fr[p]=y;
while(v!=-1&&ch[v][c]==x){
ch[v][c]=y;
v=fr[v];
}
}
int dfs(int x){
if(sg[x]!=-1)return sg[x];
bool ct[27];
for(int i=0;i<27;i++)ct[i]=0;
for(int i=0;i<26;i++){
int to=ch[x][i];
if(to==-1)continue;
ct[dfs(to)]=1;
for(int j=0;j<27;j++)cnt[x][j]+=cnt[to][j];
}
for(int i=0;i<27;i++)if(!ct[i]){sg[x]=i;break;}
cnt[x][sg[x]]++;
for(int i=0;i<27;i++)cnt[x][27]+=cnt[x][i];
return sg[x];
}
void Init(){
for(int i=0;i<26;i++)ch[0][i]=-1;fr[0]=-1;
int u=0;
for(int i=1;i<=n;i++)Addchar(u,u,S[i]-'a');
memset(sg,-1,sizeof(sg));
dfs(0);
}
void Pr(){
for(int i=0;i<=tot;i++){
printf("i:%d : ",i);
for(int j=0;j<28;j++)printf("%d ",cnt[i][j]);
printf("sg::%d\n",sg[i]);
}
}
}A,B;
LL k;
char ans[2][M];
LL cost(int u,int v){
LL res=0;
for(int i=0;i<27;i++)
res+=1LL*A.cnt[u][i]*(B.cnt[v][27]-B.cnt[v][i]);
return res;
}
int dfs(int p,int x){
LL ct=B.cnt[0][27]-B.cnt[0][A.sg[x]];
if(k<=ct)return x;
else k-=ct;
for(int i=0;i<26;i++){
int to=A.ch[x][i];
if(to==-1)continue;
LL pl=cost(to,0);
if(pl<k)k-=pl;
else {
ans[0][p]='a'+i;
return dfs(p+1,to);
}
}return -1;
}
void rdfs(int p,int x,int T){
k-=A.sg[T]!=B.sg[x];
if(k==0)return;
for(int i=0;i<26;i++){
int to=B.ch[x][i];
if(to==-1)continue;
LL pl=B.cnt[to][27]-B.cnt[to][A.sg[T]];
if(pl<k)k-=pl;
else {
ans[1][p]='a'+i;
rdfs(p+1,to,T);
return;
}
}
}
int main(){
//int size = 32 << 20; // 32MB
//char *p = (char*)malloc(size) + size;
//__asm__("movl %0, %%esp\n" :: "r"(p));
// freopen("in.in","r",stdin);
// freopen("1.out","w",stdout);
cin>>k;scanf("%s%s",A.S+1,B.S+1);
A.n=strlen(A.S+1);B.n=strlen(B.S+1);
A.Init();B.Init();
int T=dfs(0,0);
if(T==-1){printf("NO");return 0;}
rdfs(0,0,T);
puts(ans[0]);puts(ans[1]);
return 0;
}