HDU 5769 Substring(后缀数组)
来源:互联网 发布:js判断对象包含属性 编辑:程序博客网 时间:2024/05/21 10:10
题目分析
说实话前面之所以想搞后缀数组,一个是因为有了它,加上以前学的kmp和AC自动机,大部分的字符串的题目都可以解决了,第二就是看到了多校集训上面有后缀数组的题目,因此自己也向学习一下,毕竟多校的题目是区域赛的难度。
首先我们回忆一下前一天发的模板上讲的求单个子串的不重复子串个数,很明显对于每一个sa[i]后缀,它的起始位置sa[i],那么它最多能得到该后缀长度个子串(n-sa[i]个),而其中有height[i]个是与前一个后缀相同的,所以它能产生的实际后缀个数便是n-sa[i]-height[i]。遍历一次所有的后缀,将它产生的后缀数加起来便是答案。那么我们这道题是求包含x的最长不重复子串,那么很明显我们需要将x加入进去,因为所有子串都可以通过每个后缀的前缀来得到,因此我们需要找到每一个位置sa[i]的右边的最近的x的位置,这样我们就能通过一个计算式ans += (LL)n - max(f[sa[i]], sa[i]+height[i]);(其中f[sa[i]]表示每一个位置sa[i]的右边的最近的x的位置)得出答案了。
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const int maxn = 1e5+5;char s[maxn],x[2];int sa[maxn], t[maxn], t2[maxn], c[maxn], f[maxn];int Rank[maxn], height[maxn];void build_sa(int n,int m){ //求sa数组 int i,*x = t, *y = t2; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[i] = s[i]]++; for(i = 1; i < m; i++) c[i] += c[i-1]; for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i; for(int k = 1; k <= n; k <<= 1){ int p = 0; for(i = n-k; i < n; i++) y[p++] = i; for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[y[i]]]++; for(i = 0; i < m; i++) c[i] += c[i-1]; for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1,x[sa[0]] = 0; for(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; }}void getHeight(int n){ int i,j,k = 0; for(i = 0; i < n; i++) Rank[sa[i]] = i; for(i = 0; i < n-1; i++){ if(k) k--; j = sa[Rank[i]-1]; while(s[i+k] == s[j+k]) k++; height[Rank[i]] = k; }}int main(){ int T; scanf("%d", &T); for(int kase = 1; kase <= T; kase++){ memset(s, 0, sizeof(s)); memset(x, 0, sizeof(x)); scanf("%s%s", x, s); int n = strlen(s); build_sa(n+1, 255); getHeight(n+1); int cnt = n; for(int i = n-1; i >= 0; i--){ //向后找每一个位置最近的x的位置 if(s[i] == x[0]) cnt = i; f[i] = cnt; } LL ans = 0; //注意为long long,有可能越界 for(int i = 1; i <= n; i++) ans += (LL)n - max(f[sa[i]], sa[i]+height[i]); printf("Case #%d: %I64d\n", kase, ans); } return 0;}
0 0
- HDU 5769 Substring(后缀数组)
- hdu-5769-Substring-后缀数组
- hdu 5769 Substring 后缀数组
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring (后缀数组)
- Hdu-5769 Substring (SA后缀数组)
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring (后缀数组)
- HDU-5769-Substring(后缀数组)
- HDU 5769 Substring 多校赛 (后缀数组)
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring (后缀数组)
- hdu 5719Substring(后缀数组)
- HDU 1403 Longest Common Substring 【 后缀数组】
- hdu 1403 Longest Common Substring - 后缀数组
- hdu 1403 Longest Common Substring (后缀数组)
- HDU 5769 后缀数组
- 腾讯优测优分享 | Android性能测试工具化实现
- spring框架详解
- Android开发项目经验
- VS2010+OPENCV2.4.10配置
- ”MVC “与 ”三层架构“
- HDU 5769 Substring(后缀数组)
- CEPH存储时,umount时出错
- 英文高频词
- 引入包名后的java编译命令注意事项!!
- HTML正则表达式:限制Input输入类型
- 直接拿来用!最火的Android开源项目(一)
- JavaScript中有三个可以对字符串编码的函数escape()、encodeURI()、encodeURIComponent()已便在所有计算机适用
- 修改pip源,加快pip安装速度
- OSGART 官网相关信息翻译