zoukankan      html  css  js  c++  java
  • SPOJ

    题目

    求第K小子串

    题解

    建好SAM后,拓扑排序,反向传递后面所形成的串的数量
    最后从根开始,按照儿子形成串的数量与k比较走就好了

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    using namespace std;
    const int maxn = 200005,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();}
    	return out * flag;
    }
    int pre[maxn],sz[maxn],step[maxn],ch[maxn][26],cnt,last,n;
    int a[maxn],b[maxn];
    char s[maxn];
    void ins(int x){
    	int p = last,np = ++cnt;
    	last = np; step[np] = step[p] + 1;
    	while (p && !ch[p][x]) ch[p][x] = np,p = pre[p];
    	if (!p) pre[np] = 1;
    	else {
    		int q = ch[p][x];
    		if (step[q] == step[p] + 1) pre[np] = q;
    		else {
    			int nq = ++cnt; step[nq] = step[p] + 1;
    			for (int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
    			pre[nq] = pre[q]; pre[np] = pre[q] = nq;
    			while (ch[p][x] == q) ch[p][x] = nq,p = pre[p];
    		}
    	}
    }
    void walk(int k){
    	int u = 1;
    	while (k){
    		for (int i = 0; i < 26; i++) if (ch[u][i]){
    			if (sz[ch[u][i]] >= k){
    				putchar(i + 'a');
    				k--; u = ch[u][i];
    				break;
    			}else k -= sz[ch[u][i]];
    		}
    	}
    	puts("");
    }
    void solve(){
    	REP(i,cnt) b[step[i]]++;
    	REP(i,cnt) b[i] += b[i - 1];
    	REP(i,cnt) a[b[step[i]]--] = i;
    	for (int i = cnt; i; i--){
    		int u = a[i]; sz[u] = 1;
    		for (int j = 0; j < 26; j++)
    			if (ch[u][j]) sz[u] += sz[ch[u][j]];
    	}
    	int Q = read();
    	while (Q--) walk(read());
    }
    int main(){
    	scanf("%s",s + 1);
    	n = strlen(s + 1); cnt = last = 1;
    	REP(i,n) ins(s[i] - 'a');
    	solve();
    	return 0;
    }
    
    
  • 相关阅读:
    linux基础学习-6.4-Linux无法上网排查流程
    [JSOI2007][BZOJ1029] 建筑抢修
    [HNOI2003][BZOJ1216] 操作系统
    [Apio2009][BZOJ1179] Atm
    [Tjoi2013][BZOJ3172] 单词
    AC自动机学习笔记
    [转]一个比较通俗的KMP算法讲解
    [HAOI2008][BZOJ1042] 硬币购物
    [NOI2007][BZOJ1491] 社交网络
    [SCOI2009][BZOJ1295] 最长距离
  • 原文地址:https://www.cnblogs.com/Mychael/p/8298017.html
Copyright © 2011-2022 走看看