HDU5769后缀数组的简单应用
来源:互联网 发布:小米平板2怎么连接网络 编辑:程序博客网 时间:2024/05/26 02:51
题目链接http://acm.hdu.edu.cn/showproblem.php?pid=576
题目意思也就是给你一个字符x,问字符串str中有多少个包含x的子串(x在子串中至少出现一次)比赛是第一思路就是后缀数组,但无奈是今天早上才开始学习后缀数组,下午比赛的时候又是一脸懵逼,比赛后发现挺简单,最近几天也系统的学习一下后缀数组和字符串问题
首先字符串str中子串的总个数为sum(len-(sa[i]+height[i]))然后就是求解包含字符x的子串个数,只需每个离sa[i]最近位置的x的位置即可,答案即为sum(len-max(next[sa[i]],sa[i]+length[i]) 赛后补题套的是kuangbin的模板,莫名的wa,换了模板之后果断AC(同时注意答案为long long),代码奉上
#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>using namespace std;const int maxn=100000+5;int len,n;int nxt[maxn];int num[maxn];int sa[maxn], Rank[maxn], height[maxn];int wa[maxn], wb[maxn], wv[maxn], wd[maxn];int cmp(int *r, int a, int b, int l){ return r[a] == r[b] && r[a+l] == r[b+l];}void da(int *r, int n, int m){ int i, j, p, *x = wa, *y = wb, *t; for(i = 0; i < m; i ++) wd[i] = 0; for(i = 0; i < n; i ++) wd[x[i]=r[i]] ++; for(i = 1; i < m; i ++) wd[i] += wd[i-1]; for(i = n-1; i >= 0; i --) sa[-- wd[x[i]]] = i; for(j = 1, p = 1; p < n; j *= 2, m = p){ for(p = 0, i = n-j; i < n; i ++) y[p ++] = i; for(i = 0; i < n; i ++) if(sa[i] >= j) y[p ++] = sa[i] - j; for(i = 0; i < n; i ++) wv[i] = x[y[i]]; for(i = 0; i < m; i ++) wd[i] = 0; for(i = 0; i < n; i ++) wd[wv[i]] ++; for(i = 1; i < m; i ++) wd[i] += wd[i-1]; for(i = n-1; i >= 0; i --) sa[-- wd[wv[i]]] = y[i]; for(t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i ++){ x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p - 1: p ++; } }}void calHeight(int *r, int n){ // 求height数组。 int i, j, k = 0; for(i = 1; i <= n; i ++) Rank[sa[i]] = i; for(i = 0; i < n; height[Rank[i ++]] = k){ for(k ? k -- : 0, j = sa[Rank[i]-1]; r[i+k] == r[j+k]; k ++); }}char aim,str[maxn];int pos;int main(){ int l=1; int T; scanf("%d",&T); while(T--) { memset(nxt,0,sizeof(nxt)); scanf(" %c",&aim); scanf(" %s",str); len=strlen(str); for(int i=0;i<len;i++)num[i]=str[i]-'a'+1; num[len]=0; da(num,len+1,128); calHeight(num,len); nxt[len]=len; for(int i=len-1;i>=0;i--) { nxt[i]=(str[i]==aim)?i:nxt[i+1]; }// for(int i=0;i<=len;i++)// {// printf("%d ",sa[i]);// }// cout <<endl;// for(int i=0;i<=len;i++)// {// printf("%d ",height[i]);// }// cout << endl; long long ans=0; for(int i=1;i<len+1;i++) { //cout << max(nxt[sa[i]],sa[i]+height[i]) << endl; ans+=(len-max(nxt[sa[i]],sa[i]+height[i])); } printf("Case #%d: %I64d\n",l++,ans); }}
0 0
- HDU5769后缀数组的简单应用
- HDU5769之后缀数组
- HDU5769 Substring 后缀数组
- HDU5769后缀数组,高度数组模板
- (多校第四场1006)HDU5769 Substring 后缀数组
- 后缀数组的应用
- 后缀数组的应用
- 后缀数组的应用
- 后缀数组的应用
- 后缀数组的应用
- 简单的后缀数组
- 后缀数组的例题应用
- hdu1403 简单的后缀数组
- poj 1743 Musical Theme 较为简单的后缀数组+高度数组的应用
- hdu 1403 后缀数组的应用
- 后缀数组的应用 hdu 3518
- hdu3518 后缀数组的height应用
- POJ 2774(后缀数组的应用)
- 调用系统相机录像,压缩保存到相册(附仿微信视频录制demo)
- linux echo命令
- SELinux 开启和关闭
- VS2015运行OpenGL编程指南第8版的第一个示例
- windows进程间各种通信方式浅谈
- HDU5769后缀数组的简单应用
- CXF与Spring框架的整合
- Android Studio入门到精通
- 题目274 正三角形的外界圆面积
- Different sampler types for same sample texture unit in fragment shader.
- caffe命令行解析
- POJ1459
- Java-可重入锁
- Python中的MD5