zoukankan      html  css  js  c++  java
  • SPOJ Lexicographical Substring Search 后缀自动机

    给你一个字符串,然后询问它第k小的factor,坑的地方在于spoj实在是太慢了,要加各种常数优化,字符集如果不压缩一下必t。。

    #pragma warning(disable:4996)
    #include<cstring>
    #include<string>
    #include<iostream>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    #define maxn 90050
    using namespace std;
    
    struct State{
    	State *suf, *go[26];
    	int val, cnt;
    	char transch;
    	State() :suf(0), val(0){
    		memset(go, 0, sizeof(go));
    	}
    }*root, *last;
    
    State statePool[maxn * 2], *cur;
    
    void init()
    {
    	cur = statePool;
    	root = last = cur++;
    }
    
    void extend(int w)
    {
    	State *p = last, *np = cur++;
    	np->val = p->val + 1;
    	np->cnt = 1;
    	while (p&&!p->go[w]) p->go[w] = np, p = p->suf;
    	if (!p) np->suf = root;
    	else{
    		State *q = p->go[w];
    		if (p->val + 1 == q->val){
    			np->suf = q;
    		}
    		else{
    			State *nq = cur++;
    			memcpy(nq->go, q->go, sizeof q->go);
    			nq->val = p->val + 1;
    			nq->cnt = 1;
    			nq->suf = q->suf;
    			q->suf = nq;
    			np->suf = nq;
    			while (p&&p->go[w] == q){
    				p->go[w] = nq, p = p->suf;
    			}
    		}
    	}
    	last = np;
    }
    
    char str[maxn];
    char ans[maxn];
    int atop;
    int n;
    int q;
    
    int bcnt[maxn];
    State *b[maxn * 2];
    
    int main()
    {
    	scanf("%s", str);
    	n = strlen(str);
    	init();
    	for (int i = 0; i < n; i++){
    		extend(str[i] - 'a');
    	}
    	int tot = cur - statePool;
    	for (int i = 0; i < tot; i++) bcnt[statePool[i].val]++;
    	for (int i = 1; i <= n; i++) bcnt[i] += bcnt[i - 1];
    	for (int i = 0; i < tot; i++) b[--bcnt[statePool[i].val]] = statePool + i;
    	for (int i = tot - 1; i >= 0; i--){
    		int kth = 0;
    		State *p = b[i];
    		for (int j = 0; j < 26; j++){
    			if (p->go[j]){
    				p->cnt += p->go[j]->cnt;
    				p->go[kth++] = p->go[j];
    				p->go[j]->transch = 'a' + j;
    			}
    		}
    		p->go[kth] = NULL;
    	}
    	scanf("%d", &q);
    	int k;
    	while (q--)
    	{
    		scanf("%d", &k);
    		State *p = root; atop = 0;
    		while (k){
    			for (int x = 0; p->go[x]; x++){
    				if (k > p->go[x]->cnt) k -= p->go[x]->cnt;
    				else {
    					k -= 1;
    					p = p->go[x];
    					ans[atop++] = p->transch;
    					break;
    				}
    			}
    		}
    		ans[atop] = '';
    		puts(ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    leetcode Super Ugly Number
    leetcode Find Median from Data Stream
    leetcode Remove Invalid Parentheses
    leetcode Range Sum Query
    leetcode Range Sum Query
    leetcode Minimum Height Trees
    hdu 3836 Equivalent Sets
    hdu 1269 迷宫城堡
    hud 2586 How far away ?
    poj 1330 Nearest Common Ancestors
  • 原文地址:https://www.cnblogs.com/chanme/p/3551952.html
Copyright © 2011-2022 走看看