BZOJ 2251 2010Beijing WC 外星联络 后缀数组/Trie树
2015-04-07 09:42
302 查看
题目大意
给出一个字符串,问这个字符串中出现过1次以上的子串的个数,按照子串的字典序输出。思路
由于数据范围过小,这个题有两个解法。基本的想法就是用后缀数组来进行后缀的排序,之后按照height数组扫就可以了。应该是挺快的。
但是注意到数据范围只有3000,因此我们只需要弄出所有的后缀拿出来建立一颗后缀Trie树就行了。最后DFS一次树种的所有节点。
CODE
SuffixArraySuffixArray#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 3010 using 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
SuffixTrieSuffixTrie
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 10010 using 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; }
相关文章推荐
- BZOJ 2251: [2010Beijing Wc]外星联络 Trie树
- Bzoj2251 [2010Beijing Wc]外星联络
- BZOJ2251[2010Beijing Wc]外星联络
- BZOJ_2251_[2010Beijing Wc]外星联络_后缀数组
- BZOJ 2251.[2010Beijing Wc]外星联络(Trie)
- BZOJ 2251: [2010Beijing Wc]外星联络
- bzoj 2251[2010Beijing Wc]外星联络
- [SA] BZOJ 2251 [2010Beijing Wc]外星联络
- BZOJ 2251: [2010Beijing Wc]外星联络|后缀数组
- 【BZOJ 2251】[2010Beijing Wc]外星联络 后缀数组
- BZOJ 2251 [2010Beijing Wc]外星联络 trie的性质以及字符串性质
- bzoj 2251 [2010Beijing Wc]外星联络
- BZOJ 2251 [2010Beijing Wc]外星联络
- ●BZOJ 2251 [2010Beijing Wc]外星联络
- BZOJ 2251 [2010Beijing Wc]外星联络
- 【bzoj2251】[2010Beijing Wc]外星联络 后缀数组
- [bzoj2251][后缀数组][2010Beijing Wc]外星联络
- [BZOJ2251][2010Beijing Wc]外星联络(后缀数组)
- 【BZOJ2251】[2010Beijing Wc]外星联络 后缀数组
- BZOJ 2251 [2010Beijing Wc]外星联络