zoukankan      html  css  js  c++  java
  • P3975 [TJOI2015]弦论

    (color{#0066ff}{ 题目描述 })

    为了提高智商,ZJY开始学习弦论。这一天,她在《 String theory》中看到了这样一道问题:对于一个给定的长度为n的字符串,求出它的第k小子串是什么。你能帮帮她吗?

    (color{#0066ff}{输入格式})

    第一行是一个仅由小写英文字母构成的字符串s

    第二行为两个整数t和k,t为0则表示不同位置的相同子串算作一个,t为1则表示不同位置的相同子串算作多个。k的意义见题目描述。

    (color{#0066ff}{输出格式})

    输出数据仅有一行,该行有一个字符串,为第k小的子串。若子串数目不足k个,则输出-1。

    (color{#0066ff}{输入样例})

    aabc
    0 3
    
    
    aabc
    1 3
    
    
    aabc
    1 11
    

    (color{#0066ff}{输出样例})

    aab
    
    aa
    
    -1
    

    (color{#0066ff}{数据范围与提示})

    对于10%的数据,n ≤ 1000。

    对于50%的数据,t = 0。

    对于100%的数据,n ≤ 5 × 10^5, t < 2, k ≤ 10^9。

    (color{#0066ff}{ 题解 })

    求第k小字串,SAM上贪心跑就行

    但是有一些限制

    一个是相同的算一个, 一个是相同的算多个

    如果算多个,就要算出字串出现次数(鸡排倒推siz)

    贪心的时候不能再-1,要减siz(siz个相同的)

    然而。。。MLE

    本题及其卡指针

    写大鸡排5个点MLE

    写toposort1个点MLE

    幸好上帝还开了一扇窗---->数据水!!!

    TM数组少开100000居然A了(雾~

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    LL in() {
    	char ch; int x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int maxn = 9e5 + 1;
    int type;
    struct SAM {
    protected:
    	struct node {
    		node *ch[26], *fa;
    		int len, siz, num, du;
    		node(int len = 0, int siz = 0, int num = 0, int du = 0): fa(NULL), len(len), siz(siz), num(num), du(du) {
    			memset(ch, 0, sizeof ch);
    		}
    	};
    	node *root, *tail, *lst;
    	node pool[maxn];
    	int in[maxn];
    	void extend(int c) {
    		node *o = new(tail++) node(lst->len + 1, 1), *v = lst;
    		for(; v && !v->ch[c]; v = v->fa) v->ch[c] = o;
    		if(!v) o->fa = root;
    		else if(v->len + 1 == v->ch[c]->len) o->fa = v->ch[c];
    		else {
    			node *n = new(tail++) node(v->len + 1), *d = v->ch[c];
    			std::copy(d->ch, d->ch + 26, n->ch);
    			n->fa = d->fa, d->fa = o->fa = n;
    			for(; v && v->ch[c] == d; v = v->fa) v->ch[c] = n;
    		}
    		lst = o;
    	}
    	void clr() {
    		tail = pool;
    		root = lst = new(tail++) node();
    	}
    	void getnum(node *o) {
    		if(o->num) return;
    		o->num = type? o->siz : 1;
    		for(int i = 0; i <= 25; i++) if(o->ch[i]) getnum(o->ch[i]), o->num += o->ch[i]->num;
    	}
    	void kth(node *o, int k) {
    		if(!k) return;
    		for(int i = 0; i <= 25; i++) {
    			if(o->ch[i]) {
    				if(o->ch[i]->num >= k) {
    					putchar((char)i + 'a');
    					kth(o->ch[i], type? k - o->ch[i]->siz : k - 1);
    					return;
    				}
    				else k -= o->ch[i]->num;
    			}
    		}
    	}
    
    public:
    	SAM() { clr(); }
    	void ins(char *s) { for(char *p = s; *p; p++) extend(*p - 'a'); }
    	void getnum() { getnum(root); }
    	void getsiz() {
    		for(node *o = pool; o != tail; o++) if(o->fa) o->fa->du++;
    		std::queue<node*> q;
    		while(!q.empty()) q.pop();
    		for(node *o = pool; o != tail; o++) if(!o->du) q.push(o);
    		while(!q.empty()) {
    			node *o = q.front(); q.pop();
    			if(o->fa) {
    				o->fa->siz += o->siz;
    				o->fa->du--;
    				if(!o->fa->du) q.push(o->fa);
    			}
    		}
    	}
    	void kth(int k) { return kth(root, k); }
    }sam;
    char s[maxn];
    int main() {
    	scanf("%s", s);
    	type = in();
    	sam.ins(s);
    	sam.getsiz();
    	sam.getnum();
    	sam.kth(in());
    	return 0;
    }
    
  • 相关阅读:
    动画,缩放
    本地公司
    调研 公司信息
    外贸 内贸 经商
    情感 爱情 恋爱
    H5源码
    世界 生活
    标识
    Jackson
    java数据结构
  • 原文地址:https://www.cnblogs.com/olinr/p/10255809.html
Copyright © 2011-2022 走看看