zoukankan      html  css  js  c++  java
  • Lexicographical Substring Search SPOJ

    Lexicographical Substrings Search

    [Time Limit: 149 ms quad Memory Limit: 1572864 kB ]

    题意

    给出一个字符串,求出这个字符串上字典序第 (k) 小的子串。

    思路

    先对给出的字符串构建后缀自动机,因为后缀自动机上从根节点走到任意节点都是原串的一个子串,所以我们可以 (dfs) 求出节点 (i) 往后存在多少个子串。
    对于查询第 (k) 小的子串时,在用一个 (dfs) 来求,对于当前节点(u), 从(1-26) 枚举下一步的方案 (v),如果从 (v) 往后的子串比 (k) 少,那么不用往下走,直接 (k-=cnt[v])。否则往下走一步,让 (k--)。如此一直走到 (k=0) 为止。

    /***************************************************************
        > File Name    : a.cpp
        > Author       : Jiaaaaaaaqi
        > Created Time : 2019年05月22日 星期三 17时06分12秒
     ***************************************************************/
    
    #include <map>
    #include <set>
    #include <list>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <cfloat>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <bitset>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define  lowbit(x)  x & (-x)
    #define  mes(a, b)  memset(a, b, sizeof a)
    #define  fi         first
    #define  se         second
    #define  pii        pair<int, int>
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    const int    maxn = 1e5 + 10;
    const int    maxm = 1e5 + 10;
    const ll     mod  = 1e9 + 7;
    const ll     INF  = 1e18 + 100;
    const int    inf  = 0x3f3f3f3f;
    const double pi   = acos(-1.0);
    const double eps  = 1e-8;
    using namespace std;
    
    int n, m;
    int cas, tol, T;
    
    struct SAM {
    	struct Node{
    		int next[27];
    		int fa, len;
    		void init() {
    			mes(next, 0);
    			len = fa = 0;
    		}
    	} node[maxn<<1];
    	int sz, last;
    	int cnt[maxn<<1];
    	void init() {
    		sz = last = 1;
    		node[sz].init();
    		mes(cnt, 0);
    	}
    	void insert(int k) {
    		int p = last, np = last = ++sz;
    		node[np].init();
    		node[np].len = node[p].len+1;
    		for(; p&&!node[p].next[k]; p=node[p].fa)
    			node[p].next[k] = np;
    		if(p==0) {
    			node[np].fa = 1;
    		} else {
    			int q = node[p].next[k];
    			if(node[q].len == node[p].len + 1) {
    				node[np].fa = q;
    			} else {
    				int nq = ++sz;
    				node[nq] = node[q];
    				node[nq].len = node[p].len + 1;
    				node[np].fa = node[q].fa = nq;
    				for(; p&&node[p].next[k]==q; p=node[p].fa)
    					node[p].next[k] = nq;
    			}
    		}
    	}
    	void dfs(int u) {
    		if(cnt[u])	return ;
    		cnt[u] = 1;
    		for(int i=1; i<=26; i++) {
    			int v = node[u].next[i];
    			if(v) {
    				dfs(v);
    				cnt[u] += cnt[v];
    			}
    		}
    	}
    	char ss[maxn];
    	void find(int u, int k, int len) {
    		if(k==0) {
    			ss[len] = '';
    			printf("%s
    ", ss+1);
    			return ;
    		}
    		for(int i=1; i<=26; i++) {
    			int v = node[u].next[i];
    			if(v==0)	continue;
    			if(cnt[v] < k)	k -= cnt[v];
    			else {
    				k--;
    				ss[len] = 'a'+i-1;
    				find(v, k, len+1);
    				return ;
    			}
    		}
    	}
    	void solve(int k) {
    		find(1, k, 1);
    	}
    } sam;
    char s[maxn];
    
    int main() {
    	sam.init();
    	scanf("%s", s+1);
    	int len = strlen(s+1);
    	for(int i=1; i<=len; i++) {
    		sam.insert(s[i]-'a'+1);
    	}
    	sam.dfs(1);
    	// for(int i=2; i<=sam.sz; i++) {
    	//     printf("cnt[%d] = %d
    ", i, sam.cnt[i]);
    	// }
    	scanf("%d", &T);
    	while(T--) {
    		scanf("%d", &m);
    		sam.solve(m);
    	}
    	return 0;
    }
    
  • 相关阅读:
    微信公众号开发第三课 实现简单微信文本通讯
    微信公众号开发第二课 百度BAE搭建和数据库使用
    微信公众号开发第一课 预备知识和申请权限账号
    joomla3.1安装不通过Magic Quotes GPC解决方法
    获取汉字拼音的简便方法
    C#快速学习笔记(译)续一
    C#快速学习笔记(译)
    Xcode中如何集成Unity
    【ios开发】iOS App测试方案
    【IOS开发】SimPholders的使用
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/10907687.html
Copyright © 2011-2022 走看看