zoukankan      html  css  js  c++  java
  • bzoj 3998: [TJOI2015]弦论 后缀自动机

    题目大意:

    对于一个给定长度为N的字符串,求它的第K小子串是什么。

    题解:

    这道题我们可以类比着bzoj 2882: 工艺来做

    那道题是求最小的一个字符串,而这道题是要求一个k小的字符串
    所以我们瞎搞一搞就好了啊...像在平衡树上查询k小一样.

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(ll &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const ll maxn = 500010;
    struct Node{
    	int nx[26];
    	int fa,len;
    }T[maxn<<1];
    int last,nodecnt;
    ll siz[maxn<<1];
    int num[maxn<<1];
    void init(){
    	last = nodecnt = 0;
    	T[0].fa = -1;T[0].len = 0;
    }
    void insert(char cha){
    	int c = cha - 'a',cur = ++ nodecnt,p;
    	T[cur].len = T[last].len+1;
    	for(p=last;p!=-1 && !T[p].nx[c];p=T[p].fa) T[p].nx[c] = cur;
    	if(p == -1) T[cur].fa = 0;
    	else{
    		int q = T[p].nx[c];
    		if(T[q].len == T[p].len + 1) T[cur].fa = q;
    		else{
    			int co = ++ nodecnt;
    			T[co] = T[q];T[co].len = T[p].len + 1;
    			for(;p!=-1&&T[p].nx[c] == q;p=T[p].fa) T[p].nx[c] = co;
    			T[cur].fa = T[q].fa = co;
    		}
    	}last = cur;
    	++num[last];
    }
    inline void build(char *s){
    	init();int len = strlen(s);
    	for(int i=0;i<len;++i) insert(s[i]);
    }
    int q[maxn<<1],l,r;
    bool vis[maxn<<1];
    void calc_num(int ty){
    	l = 0;r = -1;
    	q[++r] = 0;vis[0] = true;
    	while(l <= r){
    		int u = q[l++];
    		for(int c=0;c<26;++c){
    			if(T[u].nx[c] && !vis[T[u].nx[c]]){
    				vis[T[u].nx[c]] = true;
    				q[++r]  = T[u].nx[c];
    			}
    		}
    	}
    	for(int i=r;i>=1;--i){
    		if(ty == 0) num[q[i]] = (bool)num[q[i]];
    		num[T[q[i]].fa] += num[q[i]];
    	}
    }
    void dfs(int u){
    	vis[u] = true;
    	siz[u] = num[u];
    	for(int c=0;c<26;++c){
    		if(T[u].nx[c]){
    			if(!vis[T[u].nx[c]]) dfs(T[u].nx[c]);
    			siz[u] += siz[T[u].nx[c]];
    		}
    	}return;
    }
    bool flag = false;
    void find(int u,ll k){
    	if(k <= num[u]) return;
    	k -= num[u];
    	for(int c=0;c<26;++c){
    		if(T[u].nx[c]){
    			if(k <= siz[T[u].nx[c]]){
    				flag = true;
    				putchar(c+'a');
    				find(T[u].nx[c],k);
    				return;
    			}k -= siz[T[u].nx[c]];
    		}
    	}return;
    }
    char s[maxn<<1];
    int main(){
    	scanf("%s",s);build(s);
    	ll T,K;read(T);read(K);
    	calc_num(T);memset(vis,0,sizeof vis);
    	num[0] = 0;dfs(0);
    	if(siz[0] < K) return puts("-1");
    	find(0,K);
    	getchar();getchar();
    	return 0;
    }
    
  • 相关阅读:
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    thinkphp使用foreach遍历的方法
    php中foreach中使用&的办法
    thinkphp做搜索功能
    数据库虚拟主机目录的配置文件
    网页响应式设计原理
    数据库常见远程连接问题
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6522905.html
Copyright © 2011-2022 走看看