BZOJ 2251 2010Beijing WC 外星联络 后缀数组/Trie树
来源:互联网 发布:js 对象数组 编辑:程序博客网 时间:2024/05/15 11:25
题目大意
给出一个字符串,问这个字符串中出现过1次以上的子串的个数,按照子串的字典序输出。
思路
由于数据范围过小,这个题有两个解法。
基本的想法就是用后缀数组来进行后缀的排序,之后按照height数组扫就可以了。应该是挺快的。
但是注意到数据范围只有3000,因此我们只需要弄出所有的后缀拿出来建立一颗后缀Trie树就行了。最后DFS一次树种的所有节点。
CODE
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAX 3010using namespace std;int len;char s[MAX];int sa[MAX],val[MAX];inline bool Same(int x,int y,int l){ return val[x] == val[y] && ((x + l >= len && y + l >= len) || (x + l < len && y + l < len && val[x + l] == val[y + l]));}void GetSuffixArray(){ static int _val[MAX],q[MAX],cnt[MAX],lim = 256; for(int i = 0; i < len; ++i) ++cnt[val[i] = s[i]]; for(int i = 1; i < lim; ++i) cnt[i] += cnt[i - 1]; for(int i = len - 1; ~i; --i) sa[--cnt[val[i]]] = i; for(int d = 1;; ++d) { int top = 0,l = 1 << (d - 1); for(int i = 0; i < len; ++i) if(sa[i] + l >= len) q[top++] = sa[i]; for(int i = 0; i < len; ++i) if(sa[i] >= l) q[top++] = sa[i] - l; for(int i = 0; i < lim; ++i) cnt[i] = 0; for(int i = 0; i < len; ++i) ++cnt[val[q[i]]]; for(int i = 1; i < lim; ++i) cnt[i] += cnt[i - 1]; for(int i = len - 1; ~i; --i) sa[--cnt[val[q[i]]]] = q[i]; lim = 0; for(int i = 0,j; i < len; ++lim) { for(j = i; j < len - 1 && Same(sa[j],sa[j + 1],l); ++j); for(; i <= j; ++i) _val[sa[i]] = lim; } for(int i = 0; i < len; ++i) val[i] = _val[i]; if(len == lim) break; } return ;}int height[MAX],_rank[MAX];void GetHeight(){ for(int i = 0; i < len; ++i) _rank[sa[i]] = i; for(int i = 0,k = 0; i < len; ++i) { if(!_rank[i]) continue; if(k) --k; int j = sa[_rank[i] - 1]; while(s[i + k] == s[j + k]) ++k; height[_rank[i]] = k; }}int main(){ scanf("%d%s",&len,s); GetSuffixArray(); GetHeight(); for(int i = 0; i < len; ++i) for(int j = height[i] + 1,l,r; sa[i] + j - 1 < len; ++j) { for(l = i; ~l && height[l] >= j; --l); for(r = i + 1; r < len && height[r] >= j; ++r); if(r - l > 1) printf("%d\n",r - l); } return
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAX 10010using namespace std;struct Trie{ Trie *son[2]; int cnt; Trie():cnt(0) { son[0] = son[1] = NULL; }}*root = new Trie();int length;char s[MAX];inline void Insert(char *s){ Trie *now = root; while(*s != '\0') { if(now->son[*s == '1'] == NULL) now->son[*s == '1'] = new Trie(); now = now->son[*s == '1']; ++now->cnt; ++s; }}void DFS(Trie *now){ if(now == NULL) return ; if(now->cnt > 1) printf("%d\n", now->cnt); DFS(now->son[0]); DFS(now->son[1]);}int main(){ scanf("%d%s", &length, s); for(int i = 0; i < length; ++i) Insert(s + i); DFS(root); return 0;}
0 0
- BZOJ 2251 2010Beijing WC 外星联络 后缀数组/Trie树
- BZOJ 2251: [2010Beijing Wc]外星联络|后缀数组
- BZOJ 2251 Beijing WC 2010 外星联络 后缀数组
- 【BZOJ 2251】[2010Beijing Wc]外星联络 后缀数组
- bzoj 2251: [2010Beijing Wc]外星联络 (后缀数组)
- BZOJ 2251: [2010Beijing Wc]外星联络 Trie树
- [2010Beijing Wc]外星联络 后缀数组
- 2251: [2010Beijing Wc]外星联络 后缀数组
- BZOJ 2251 [2010Beijing Wc]外星联络
- BZOJ 2251 [2010Beijing Wc]外星联络
- bzoj 2251 [2010Beijing Wc]外星联络
- BZOJ 2251.[2010Beijing Wc]外星联络(Trie)
- [BZOJ2251][2010Beijing Wc]外星联络(后缀数组)
- BZOJ2251: [2010Beijing Wc]外星联络 后缀数组
- bzoj2251[2010Beijing Wc]外星联络 后缀数组
- bzoj2251 [2010Beijing WC]外星联络(后缀数组+暴力)
- [bzoj2251][后缀数组][2010Beijing Wc]外星联络
- BZOJ 2251 [2010Beijing Wc]外星联络 trie的性质以及字符串性质
- 通过反射通过名字在res 里面获取ID
- Android UI Automated Testing(译文)
- Unable to execute dex: Multiple dex files define 解决方法
- Android--requestWindowFeature()的应用
- ANDROID开发之SQLite详解
- BZOJ 2251 2010Beijing WC 外星联络 后缀数组/Trie树
- AspNet MVC4 教学-3:AspNet MVC4 根据登录姓名的不同转向不同的View
- Java 获取指定日期的方法总结
- EasyMock 使用方法与原理剖析
- LRUCache
- C++primer(第四版)复习笔记—第二篇:容器和算法
- char、varchar、nchar、nvarchar的区别
- Qt学习之路_6(Qt局域网聊天软件)
- java swing 复选JCheckBox组件美化