题目地址:https://cn.vjudge.net/problem/SPOJ-SUBLEX

解题思路:


这道题用后缀数组也很好做,参见例题HDU5008,此处用SAM做。

建好SAM,根据得到的拓扑序,可以推得从每个状态出发的子串数目。

void getsum()//从某个状态点出发能有多少个子串
{//倒推,i是拓扑序的序号for(int i = num; i >= 1; i--){sum[y[i]] = 1;//默认值为1,因为从自己不出发就能形成一个子串for(int j = 0; j <= 25; j++)sum[y[i]] += sum[trans[y[i]][j]];}
}

现在相当于得到一个这样的东西:

现在只需利用getsum函数得到的信息在这个上面寻找字典序第k小的子串了

ac代码:


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 9e4+100;
int maxlen[maxn<<1], trans[maxn<<1][30], link[maxn<<1];
int x[maxn<<1], y[maxn<<1], cnt[maxn<<1];
int num, last;//num表示状态数
char s[maxn];
int sum[maxn<<1];//与状态数有关,开两倍
void init()
{num = last = 1;//起始状态的编号为1maxlen[last] = link[last] = 0;//起始位置为空字符,长度为0
}
void insert(int id)
{int z = ++num, p;maxlen[z] = maxlen[last]+1;for(p = last; p && !trans[p][id]; p = link[p]) trans[p][id] = z;if(!p) link[z] = 1;//路径上不存在跳转else//连接路径上已存在跳转{int x = trans[p][id];//第一个存在跳转的状态跳转去的状态if(maxlen[x] == maxlen[p]+1) link[z] = x;//一个else//多个{int y = ++num;maxlen[y] = maxlen[p]+1;memcpy(trans[y], trans[x], sizeof(trans[x]));link[y] = link[x];for(; p && trans[p][id] == x; p = link[p]) trans[p][id] = y;link[x] = link[z] = y;}}last = z;cnt[z] = 1;
}void count()
{memset(x, 0, sizeof x);for(int i = 1; i <= num; i++) x[maxlen[i]]++;for(int i = 1; i <= num; i++) x[i] += x[i-1];for(int i = 1; i <= num; i++) y[x[maxlen[i]]--] = i;for(int i = num; i >= 1; i--)cnt[link[y[i]]] += cnt[y[i]];//得到每个状态的字符串集出现的次数
}
void getsum()//从某个状态点出发能有多少个子串
{//倒推,i是拓扑序的序号for(int i = num; i >= 1; i--){sum[y[i]] = 1;//默认值为1,因为从自己不出发就能形成一个子串for(int j = 0; j <= 25; j++)sum[y[i]] += sum[trans[y[i]][j]];}
}
void get_Ksub(int k)
{int cur = 1, nxt;string ans = "";while(k){for(int i = 0; i <= 25; i++){if(trans[cur][i] && k){nxt = trans[cur][i];if(k > sum[nxt]) k -= sum[nxt];else{k--;//字典序增大1cur = nxt;ans += char(i+'a');break;}}}}cout << ans << endl;
}
int main()
{scanf("%s", s);int len = strlen(s), q, k;init();for(int i = 0; i < len; i++) insert(s[i]-'a');count();getsum();scanf("%d", &q);while(q--){scanf("%d", &k);get_Ksub(k);}return 0;
}

【SPOJ-SUBLEX】Lexicographical Substring Search(字典序第k小的子串(不重复统计同一个子串)---后缀自动机)相关推荐

  1. SPOJ - SUBLEX Lexicographical Substring Search(后缀自动机)

    题目链接:点击查看 题目大意:给出一个字符串 s ,再给出 m 次询问,每次询问需要回答字符串中第 k 小的的子串(去重后) 题目分析:可以先对字符串 s 构造SAM,因为是去重后的子串,正好对应了S ...

  2. spoj SUBLEX (Lexicographical Substring Search) RE的欢迎来看看

    SPOJ.com - Problem SUBLEX 这么裸的一个SAM,放在了死破OJ上面就是个坑. 注意用SAM做的时候输出要用一个数组存下来,然后再puts,不然一个一个字符输出会更慢. 还有一个 ...

  3. 【luogu SP7258】SUBLEX - Lexicographical Substring Search

    SUBLEX - Lexicographical Substring Search 题目链接:luogu SP7258 题目大意 给你一个字符串,要你求字典序第 k 大的子串. (相同的子串算只一个) ...

  4. SPOJ 7258 Lexicographical Substring Search(后缀自动机)

    题目链接:http://www.spoj.com/problems/SUBLEX/ 题意:给定一个字符串,每次询问第K小的串. 思路:建立自动机.cnt[p]=sigama(cnt[son[p][i] ...

  5. SP7258 SUBLEX - Lexicographical Substring Search(后缀自动机)

    传送门 解题思路 首先建\(sam\),然后在拓扑序上\(dp\)一下,把每个点的路径数算出来,然后统计答案时就在自动机上\(dfs\)一下,仿照平衡树那样找第\(k\)小. 代码 #include& ...

  6. spoj7258 SUBLEX Lexicographical Substring Search

    http://www.elijahqi.win/archives/3001 题意翻译 给定一个字符串,求排名第k小的串 注意样例的\n是换行 输入格式: 第一行给定主串(len<=90000) ...

  7. SPOJ7258 SUBLEX - Lexicographical Substring Search

    传送门[洛谷] 心态崩了我有妹子 靠 我写的记忆化搜索 莫名WA了 然后心态崩了 当我正要改成bfs排序的时候 我灵光一动 md我写的i=0;i<25;i++??? 然后 改过来就A掉了T^T ...

  8. [SPOJ7258]Lexicographical Substring Search

    [SPOJ7258]Lexicographical Substring Search 试题描述 Little Daniel loves to play with strings! He always ...

  9. Leetcode 440.字典序第k小的数字

    字典序第k小的数字 给定整数 n 和 k,找到 1 到 n 中字典序第 k 小的数字. 注意:1 ≤ k ≤ n ≤ 109. 示例 : 输入: n: 13 k: 2 输出: 10 解释: 字典序的排 ...

  10. 【SPOJ 7258】Lexicographical Substring Search

    http://www.spoj.com/problems/SUBLEX/ 好难啊. 建出后缀自动机,然后在后缀自动机的每个状态上记录通过这个状态能走到的不同子串的数量.该状态能走到的所有状态的f值的和 ...

最新文章

  1. 提高项目执行力的六板斧
  2. 苹果六电池_昆明苹果手机售后维修地址 昆明苹果手机维修哪家好?
  3. S/4HANA的生产订单,哪个字段可以用来做生产完成的标志位
  4. 怎么学习前端开发?求推荐学习路线?
  5. sliverappbar高度,SliverAppBar的最小高度(颤振)?
  6. Unieap3.5-Grid翻页不提示修改
  7. RGB图像中值平滑和均值平滑
  8. Protocol(协议)(二十)
  9. Java web 部分参考手册(CHM)资源
  10. CSC 命令编译cs文件
  11. 搜索 阿虚同学_阿虚
  12. 华为m40怎么升级鸿蒙,华为再亮剑,这四款手机将支持升级鸿蒙系统,网友:够给力!...
  13. 强大的装逼,表白,炫富,恶搞短视频制作神器微信小程序源码支持多种流量主
  14. 手机屏幕材料区别 TFT和OLED
  15. cad二次开发-C#-VS-镜像-判断用户当前是否已选择实体-将实体对象添加到模型空间-添加实体到块表记录-将块定义插入到模型空间
  16. 北工大2009计算机系新生李洋,强势围观!初次入校,请您多多关照……
  17. 筑基期第一式:SpringMVC源码解析
  18. 大智慧新一代 分笔数据提取工具 更新
  19. 泰拉瑞亚php,《泰拉瑞亚》评测:“真·全平台”和3000万销量
  20. 2021年处暑是什么时候?处暑的习俗有哪些?

热门文章

  1. 脏读,幻读,不可重复读的区别
  2. redhat linux 中用锐捷客服端实现上网
  3. Can't use Subversion command line client: svn Probably the path to Subversion executable is wrong
  4. sever2008 ad用户和计算机不见,windows-server-2008 – 当我使用Powershell将用户添加到安全组时,它们不会显示在AD中...
  5. 系统开机 linux 时间不对,linux下查看系统运行时间和最近一次的开机启动时间
  6. eureka 注册中心高可用失败,没有互为副本
  7. python实用宝典_python 5个实用的技巧
  8. linux查看端口出现unix,linux查看端口被占用状况
  9. treeset java api_JAVAAPI学习值TreeSet类
  10. css3伸缩布局(附实例、图解)