HDU 5769后缀数组
来源:互联网 发布:lte中d2怎么优化 编辑:程序博客网 时间:2024/05/01 01:46
http://acm.hdu.edu.cn/showproblem.php?pid=5769
题意:给你一个串,问你含某个特定的字符的不同子串有多少种。。
思路:使用后缀数组。。很久之前看过做过几个模板水题。。以为自己做不到这么高深的题目。。结果这次就卡了,想hash莽一下发现很不科学,就放弃了。。看来后缀数组也已经是标配了。。赶紧再补充补充自己。。
首先退一步讲,后缀数组如何求不同子串个数。。。其实就是利用排序的性质来解决。。假设我们得到了sa和height。。那么我们来枚举每一个后缀串对于答案的贡献。。显然不考虑重复肯定是len-sa[ i ]。。也就是总长度减去现在的位置,这个很好理解。。那么如何去除重复呢?利用排序的性质和height的意义。。也就是排序好的相邻的最长公共前缀。。那么我们就可以知道有多少是重复的,这样就是len-sa[ i ]-height[ i ]。。到这里问题基本就解决了。
回到这个题目,要包含某个特定的字符,其实如果知道每个后缀串要做出贡献至少要多长就可以。。如果知道了,套用上面的就好啦~
PS。后缀数组的原理还是不是很懂。。不过重在应用。。慢慢学习。。
代码:
#include <bits/stdc++.h>using namespace std;const int MAXN=200010;int t1[MAXN],t2[MAXN],c[MAXN];//求SA数组需要的中间变量,不需要赋值bool cmp(int *r,int a,int b,int l){ return r[a] == r[b] && r[a+l] == r[b+l];}void da(int str[],int sa[],int ran[],int height[],int n,int m){ n++; int i, j, p, *x = t1, *y = t2; for(i = 0; i < m; i++)c[i] = 0; for(i = 0; i < n; i++)c[x[i] = str[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(j = 1; j <= n; j <<= 1){ p = 0; for(i = n-j; i < n; i++)y[p++] = i;//后面的j个数第二关键字为空的最小 for(i = 0; i < n; i++)if(sa[i] >= j)y[p++] = sa[i] - j; for(i = 0; i < m; i++)c[i] = 0; for(i = 0; i < n; i++)c[x[y[i]]]++; for(i = 1; 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]] = cmp(y,sa[i-1],sa[i],j)?p-1:p++; if(p >= n)break; m = p;//下次基数排序的最大值 } int k = 0; n--; for(i = 0; i <= n; i++)ran[sa[i]] = i; for(i = 0; i < n; i++){ if(k)k--; j = sa[ran[i]-1]; while(str[i+k] == str[j+k])k++; height[ran[i]] = k; }}int ran[MAXN],height[MAXN];char str[MAXN];int r[MAXN];int sa[MAXN];int nxt[MAXN];int main(){ int t,cas=1; scanf("%d",&t); while(t--){ char X[2]; scanf("%s%s",X,str); int len = strlen(str); for(int i = 0; i < len; i++)r[i] = str[i]; r[len] = 0; da(r,sa,ran,height,len,128); int pr=-1; for(int i=len-1;i>=0;i--){ if(X[0]==str[i]) pr=i; nxt[i]=pr; } long long ans=0; for(int i=1;i<=len;i++){ if(nxt[sa[i]]!=-1) ans+=len-max(nxt[sa[i]],height[i]+sa[i]); } printf("Case #%d: %lld\n",cas++,ans); }}
0 0
- HDU 5769 后缀数组
- HDU 5769 (后缀数组)
- hdu 5769 后缀数组
- HDU 5769后缀数组
- hdu 5769-后缀数组
- hdu 5769 后缀数组
- HDU 5769 Substring(后缀数组)
- hdu-5769-Substring-后缀数组
- hdu 5769 Substring 后缀数组
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring (后缀数组)
- HDU 5769 后缀数组+二分
- Hdu-5769 Substring (SA后缀数组)
- HDU 5769 Substring(后缀数组)
- HDU 5769 Substring (后缀数组)
- HDU-5769-Substring(后缀数组)
- HDU 5769 Substring 多校赛 (后缀数组)
- 如何向html表格中输入文本
- 缓动类算法
- 数据库
- 单例模式中的饿汉式和懒汉式(Java设计模式)
- golang年度使用总结,简洁不简单
- HDU 5769后缀数组
- SDUT3345数据结构实验之二叉树六:哈夫曼编码
- LintCode:背包问题
- 【Arduino】1.3 按键的使用进阶
- 【知识点】bit-band(stm32)
- POJ 2449 Remmarguts' Date [第k短路]
- Aizu 0189 Convenient Location 【全局最短路 floyd】
- mysql 主从原理
- iOS 开发可视化编程之Xib 简述