BZOJ3998 [TJOI2015]弦论 SAM

建一个\(SAM\) 如果\(T=0\)也就是本质不同的串直接在\(SAM\)上统计就好 如果\(T=1\)先拓扑序用\(parent\)树转移求出本质相同的串

后面都是做相同的\(dfs\)求出结果就好

#include<bits/stdc++.h>
using namespace std;
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define pa pair<int,int>
#define mod 1000000007
#define ll long long
#define mk make_pair
#define pb push_back
#define fi fisrt
#define se second
#define cl(x) memset(x,0,sizeof x)
#ifdef Devil_Gary
#define bug(x) cout<<(#x)<<" "<<(x)<<endl
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define bug(x)
#define debug(...)
#endif
const int INF = 0x7fffffff;
const int N=1e6+5;
/*
char *TT,*mo,but[(1<<15)+2];
#define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/
inline int read(){
    int x=0,rev=0,ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return rev?-x:x;
}
int T,tot,n,k,rt,sum[N<<1],last,par[N<<1],c[N<<1][26],len[N<<1],sz[N<<1],b[N<<1],w[N];
char s[N];
void extend(int x){
	int p=last,np=++tot;len[np]=len[p]+1;sz[np]=1;
	for(;p&&!c[p][x];p=par[p]) c[p][x]=np;
	if(!p) par[np]=rt;
	else {
		int q=c[p][x];
		if(len[q]==len[p]+1) par[np]=q;
		else {
			int nq=++tot;
			len[nq]=len[p]+1;
			memcpy(c[nq],c[q],sizeof c[q]);
			par[nq]=par[q],par[q]=par[np]=nq;
			for(;p&&c[p][x]==q;p=par[p]) c[p][x]=nq;
		}
	} 
	last=np;
}
void dfs(int x){
	if(k<=sz[x]) return ;
	k-=sz[x];
#define sz sum
	for(int i=0;i<26;i++){
		if(!sz[c[x][i]]) continue;
		if(sz[c[x][i]]<k) k-=sz[c[x][i]];
		else {
			putchar(i+'a');
			dfs(c[x][i]);
			return;
		}
	}
#undef sz
}
int main(){
#ifdef Devil_Gary
	freopen("in.txt","r",stdin);
#endif
	scanf("%s",s+1),n=strlen(s+1),rt=tot=last=1,T=read(),k=read();
	for(int i=1;i<=n;i++) extend(s[i]-'a');
	for(int i=1;i<=tot;i++) w[len[i]]++;
	for(int i=1;i<=n;i++) w[i]+=w[i-1];
	for(int i=1;i<=tot;i++) b[w[len[i]]--]=i;
	for(int i=tot;i>1;i--){
		int j=b[i];
		if(T)sz[par[j]]+=sz[j];
		else sz[j]=1;
	}
	bug(sz[rt]);
	sz[rt]=0;
	for(int i=tot;i;i--){
		int k=b[i]; 
		sum[k]=sz[k];
		for(int j=0;j<26;j++){
			if(c[k][j]) sum[k]+=sum[c[k][j]];
		}
	}
	bug(sum[rt]);
	if(k>sum[rt]) return puts("-1"),0;
	dfs(rt);
}
posted @ 2018-04-20 15:32  Devil_Gary  阅读(171)  评论(0编辑  收藏  举报