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;
    }
    
  • 相关阅读:
    周总结3
    周总结6
    Java时间日期格式转换
    [专贴]在使用了母版页的内容页后,如何在javascript中调用服务器控件值
    用到函数的题目
    javascript解析dom(2)
    javascript解析dom
    自己的分页
    javascript解析DOM(3)
    转载 ajax XML dataset
  • 原文地址:https://www.cnblogs.com/chanme/p/3551952.html
Copyright © 2011-2022 走看看