SPOJ 694 后缀数组
来源:互联网 发布:淘宝大马士革刀真假 编辑:程序博客网 时间:2024/06/07 18:40
简略题意:求不相同的子串的个数。
求出sa之后,会发现每按名次加入一个后缀,会产生n-sa[i]个新的子串,其中有height[i]个之前已经出现过。答案为n-sa[i]+height[i]。
#include <iostream>#include <cstring>#include <map>#include <cstdio>#include <vector>#include <algorithm>using namespace std;struct SuffixArray{ static const int maxn = 1e6+7; int s[maxn], n, m; int sa[maxn], rank[maxn], height[maxn]; int t[maxn], t2[maxn], c[maxn]; int MIN[maxn][30]; void build_sa(){ s[n++] = 0; int *x = t, *y = t2; for(int i=0; i<m; i++) c[i] = 0; for(int i=0; i<n; i++) c[x[i]=s[i]]++; for(int i=1; i<m; i++) c[i]+=c[i-1]; for(int i=n-1; i>=0; i--) sa[--c[x[i]]] = i; for(int k=1; k<=n; k<<=1){ int p = 0; for(int i=n-k; i<n; i++) y[p++] = i; for(int i=0; i<n; i++) if(sa[i]>=k) y[p++] = sa[i]-k; for(int i=0; i<m; i++) c[i] = 0; for(int i=0; i<n; i++) c[x[y[i]]]++; for(int i=1; i<m; i++) c[i]+=c[i-1]; for(int i=n-1; i>=0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[sa[0]] = 0; for(int i=1; i<n; i++) x[sa[i]] = y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p >= n) break; m=p; } n--; } void getheight(){ int k = 0; for(int i=1; i<=n; i++) rank[sa[i]] = i; for(int i=0; i<n; i++){ if(k) k --; int j = sa[rank[i]-1]; while(s[i+k] == s[j+k]) k++; height[rank[i]] = k; } } void RMQ_init(){ for(int i=0; i<n; i++) MIN[i][0] = height[i+1]; for(int j=1; (1<<j)<=n; j++){ for(int i=0; i+(1<<j)<=n; i++){ MIN[i][j] = min(MIN[i][j-1], MIN[i+(1<<(j-1))][j-1]); } } } int RMQ(int L, int R){ int k = 0; while((1<<(k+1)) <= R-L+1) k++; return min(MIN[L][k], MIN[R-(1<<k)+1][k]); } int LCP(int i, int j){ if(rank[i] > rank[j]) swap(i, j); return RMQ(rank[i], rank[j]-1); } void init(char *str, int _n){ m = 130; n = _n; memset(height, 0, sizeof height); for(int i=0; i<n; i++) s[i] = (int)str[i]; build_sa(); getheight(); RMQ_init(); } int check(int x, int k) { int cnt = 1; for(int i = 2; i <= n; i++) { if(height[i] >= x) { cnt ++; if(cnt >= k) return 1; } else { cnt = 1; } } return cnt >= k; } void solve() { int cnt = 0; for(int i = 1; i <= n; i++) cnt += n - sa[i] - height[i]; printf("%d\n", cnt); }}suffix;int t;char str[1100];int main() { scanf("%d", &t); while(t--) { scanf("%s", str); suffix.init(str, strlen(str)); suffix.solve(); } return 0;}
阅读全文
0 0
- SPOJ 694 后缀数组
- SPOJ 694(后缀数组)
- spoj 694&&705 后缀数组
- SPOJ 694(后缀数组)
- SPOJ 694&705 后缀数组
- SPOJ 694/705 后缀数组
- spoj 694,705 后缀数组,后缀自动机
- SPOJ 694 求不同子串数 后缀数组
- SPOJ 694 Distinct Substrings(后缀数组)
- 【后缀数组】【spoj 694】Distinct Substrings
- SPOJ 694 DISUBSTR Distinct Substrings 后缀数组
- spoj 694 Distinct Substrings (后缀数组应用)
- spoj 694 Distinct Substrings(后缀数组)
- spoj 694 Distinct Substrings (后缀数组)
- SPOJ 694 Distinct Substrings 后缀数组 模板
- SPOJ 694 Distinct Substrings(后缀数组)
- spoj 694 Distinct Substrings 后缀数组
- SPOJ 694 Distinct Substrings 后缀数组
- wpf中如何将窗口设置为透明
- c# 命令行操作数据库并将数据导出到csv
- SpringMVC的注解
- C#结构体+结构体与类的区别
- IOS-TableView里面cell的显示动画
- SPOJ 694 后缀数组
- 堆的概念以及实现堆
- 自己实现一个Native方法的调用
- 插入排序
- 【LAYABOX】轴心点的解释说明
- Spark源码分析之job提交后转换为Stage
- 那些年你用过的工具--网络工具Wireshark经验谈
- MFC中,在图片上添加汉字(c++实现)
- 关于停车计费系统的几个问题