3998: [TJOI2015]弦论

题解:

每个点的size值就是这个从根-它出现的次数

如果相同只算一次就全部赋值为1就可以了

代码:

#include <bits/stdc++.h>
#define ll long long
#define rint register ll
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
using namespace std;
const ll N=1.1e6;
char s[N];
ll size[N],len[N],ch[N][26],sum[N];
ll lst=1,node=1,t[N],a[N],fa[N],T,k;
void extend(ll c)
{
  ll f=lst,p=++node; lst=p;
  len[p]=len[f]+1; size[p]=1;
  while (f&&!ch[f][c]) ch[f][c]=p,f=fa[f];
  if (!f) { fa[p]=1; return;};
  ll x=ch[f][c],y=++node;
  if (len[f]+1==len[x]) {fa[p]=x; node--;return;};
  len[y]=len[f]+1; fa[y]=fa[x]; fa[x]=fa[p]=y;
  memcpy(ch[y],ch[x],sizeof(ch[x]));
  while (f&&ch[f][c]==x) ch[f][c]=y,f=fa[f];
}
void dfs(ll x)
{
  if (k<=size[x]) 
  {
    k=0;
    return;
  }
  k-=size[x];
  rep(i,0,25)
  {
    ll y=ch[x][i];
    if (k<=sum[y])
    {
      char cc=i+'a';
      cout<<cc;
      dfs(y);
      return;
    } else k-=sum[y];
  }
}
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout); 
  ios::sync_with_stdio(false);
  cin>>s;
  cin>>T>>k;
  ll l=strlen(s);
  rep(i,1,l) extend(s[i-1]-'a');
  rep(i,1,node) t[len[i]]++;
  rep(i,1,node) t[i]+=t[i-1];
  rep(i,1,node) a[t[len[i]]--]=i;
  dep(i,node,1)
  {
    ll x=a[i];
    if (T) size[fa[x]]+=size[x]; else size[x]=1; 
  }
  size[0]=size[1]=0;
  dep(i,node,1)
  {
    ll x=a[i];
    sum[x]+=size[x];
    rep(j,0,25) sum[x]+=sum[ch[x][j]];
  }
  dfs(1);
  if (k) cout<<-1<<endl;
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/yinwuxiao/p/9350602.html