• P3975 [TJOI2015]弦论


    题目描述

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

    输入格式

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

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

    输出格式

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

    输入输出样例

    输入 #1

    aabc
    0 3
    

    输出 #1

    aab
    

    输入 #2

    aabc
    1 3
    

    输出 #2

    aa
    

    输入 #3

    aabc
    1 11
    

    输出 #3

    -1
    

    说明/提示

    数据范围

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

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

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

    其实我对sam还不是很透彻只是似懂非懂

    只放代码吧

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 2e6+5; // 两倍空间 , 一次插入可能产生两个节点
    int n , tot = 1 , las = 1;
    int len[N] , fa[N] , tr[N][26] , a[N] , t[N];
    long long siz[N] , sum[N];
    char c[N];
    
    void Insert(int c) // 板子又一次出锅
    {
    	int cur = ++tot , p = las; len[cur] = len[las] + 1; las = cur; siz[cur] = 1;
    	for( ; p && tr[p][c] == 0 ; p = fa[p]) tr[p][c] = cur;
    	if(p == 0) fa[cur] = 1;
    	else
    	{
    		int q = tr[p][c];
    		if(len[q] == len[p] + 1) fa[cur] = q;
    		else
    		{// 这里的nq的siz不能设为 1
    			int nq = ++tot;/*siz[tot] = 1;*/ fa[nq] = fa[q]; len[nq] = len[p] + 1;
    			for(int i = 0 ; i < 26 ; ++i) tr[nq][i] = tr[q][i];
    			fa[cur] = fa[q] = nq;
    			for( ; p && tr[p][c] == q ; p = fa[p]) tr[p][c] = nq;
    		}
    	}
    }
    
    int main()
    {
    	scanf("%s",c+1); n = strlen(c+1);
    	int T , K; scanf("%d %d" , &T , &K);
    	for(int i = 1 ; i <= n ; ++i) Insert(c[i] - 'a');
    	for(int i = 1 ; i <= tot ; ++i) t[len[i]]++;
    	for(int i = 1 ; i <= tot ; ++i) t[i] += t[i-1];
    	for(int i = 1 ; i <= tot ; ++i) a[t[len[i]]--] = i;
    	// tr 与 fa 并不是一个东西 , 
    	// tr 表示在这个状态后加上 i 会到达的状态 , 
    	// fa 是后缀中第一个endpos不同于它本身的后缀的状态
    	for(int i = tot ; i >= 1 ; --i) 
    	{
    		int x = a[i];
    		if(T == 1) siz[fa[x]] += siz[x];
    		else siz[x] = 1;
    	}
    	siz[1] = 0;
    	for(int i = tot ; i >= 1 ; --i)
    	{
    		int x = a[i]; sum[x] = siz[x];
    		for(int j = 0 ; j < 26 ; ++j)
    			if(tr[x][j]) sum[x] += sum[tr[x][j]];
    	}
    	if(sum[1] < K) puts("-1");
    	else
    	{
    		int now = 1; K -= siz[now];
    		while(K > 0)
    		{
    			int i = 0;
    			while(K > sum[tr[now][i]])
    			{
    				K -= sum[tr[now][i]];
    				i++;
    			}
    			now = tr[now][i]; putchar(i + 'a');
    			K -= siz[now];
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    WCF三种通信方式
    Linux发布WebApi
    Supervisor Linux程序进程管理
    Centos安装Mongodb
    本地网址连不上远程mysql问题
    .Net之垃圾回收算法
    .Net之托管堆资源分配
    Centos7+ASP.Net Core 运行
    ASP .Net Core 使用 Dapper 轻型ORM框架
    转载 Jquery中AJAX参数详细介绍
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/12150381.html
Copyright © 2020-2023  润新知