SPOJ-694-求字符串中不同子串个数(后缀数组)
来源:互联网 发布:js跳转指定页面 编辑:程序博客网 时间:2024/06/06 16:30
http://www.spoj.com/status/ns=17418952
【每一个子串必然是某个后缀的前缀】,因此我们统计出所有的后缀中有多少个不同的前缀,就是所有不重复子串的数量了
而这个相同的前缀个数,当然就是所有height之和啦。
所以答案就是n*(n-1)/2-∑height[i]
#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<vector>#include<algorithm>using namespace std;const int N = 1050;int cmp(int *r,int a,int b,int l){ return (r[a]==r[b]) && (r[a+l]==r[b+l]);}// 用于比较第一关键字与第二关键字,// 比较特殊的地方是,预处理的时候,r[n]=0(小于前面出现过的字符)/* DA(aa,sa,n+1,200); calheight(aa,sa,n);*/int wa[N],wb[N],ws[N],wv[N];int rank[N],height[N];void DA(int *r,int *sa,int n,int m) //此处N比输入的N要多1,为人工添加的一个字符,用于避免CMP时越界{ int i,j,p,*x=wa,*y=wb,*t; for(i=0; i<m; i++) ws[i]=0; for(i=0; i<n; i++) ws[x[i]=r[i]]++; for(i=1; i<m; i++) ws[i]+=ws[i-1]; for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i; //预处理长度为1 for(j=1,p=1; p<n; j*=2,m=p) //通过已经求出的长度J的SA,来求2*J的SA { 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; //利用长度J的,按第二关键字排序 for(i=0; i<n; i++) wv[i]=x[y[i]]; for(i=0; i<m; i++) ws[i]=0; for(i=0; i<n; i++) ws[wv[i]]++; for(i=1; i<m; i++) ws[i]+=ws[i-1]; for(i=n-1; i>=0; i--) sa[--ws[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++; //更新名次数组x[],注意判定相同的 }}void calheight(int *r,int *sa,int n) // 此处N为实际长度{ int i,j,k=0; // height[]的合法范围为 1-N, 其中0是结尾加入的字符 for(i=1; i<=n; i++) rank[sa[i]]=i; // 根据SA求RANK for(i=0; i<n; height[rank[i++]] = k ) // 定义:h[i] = height[ rank[i] ] for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++); //根据 h[i] >= h[i-1]-1 来优化计算height过程}int n;char ss[N];int aa[N];int sa[N];int solve(){ DA(aa,sa,n+1,128); calheight(aa,sa,n); int ans=0; for (int i=1;i<=n;i++) { ans+=n-sa[i]-height[i]; } return ans;}int main (){ int t; scanf("%d",&t); while(t--) { scanf("%s",&ss); n=strlen(ss); for (int i=0; i<n; i++) aa[i]=ss[i]; aa[n]=0; int ans=solve(); printf("%d\n",ans); } return 0;}
0 0
- SPOJ-694-求字符串中不同子串个数(后缀数组)
- spoj 694 Distinct Substrings(求不同的子串个数,后缀数组基础题)
- SPOJ 题目694 Distinct Substrings(后缀数组,求不同的子串个数)
- SPOJ 题目705 New Distinct Substrings(后缀数组,求不同的子串个数)
- SPOJ 694、705 后缀数组:求不同子串
- spoj 405 求不同子串的个数 后缀数组和高度数组的应用
- spoj 694 求一个字符串中不同子串的个数
- spoj 694 求一个字符串中不同子串的个数
- SPOJ 705(后缀数组求单个子串的不重复子串个数)
- SPOJ 694/705 Distinct Substrings ( 后缀数组 不同子串个数 )
- SPOJ 705 子串个数 后缀数组
- SPOJ 694 求不同子串数 后缀数组
- spoj 694 求不同子串的个数
- SPOJ 694 求一个字符串有多少子串 后缀数组
- spoj 694 & spoj 705 Distinct Substrings (不同字串的个数 后缀数组)
- SPOJ DISUBSTR-----后缀数组求串的子串的个数
- SPOJ - DISUBSTR Distinct Substrings(后缀数组求不相同的子串个数)
- SPOJ 694 / SPOJ DISUBSTR Distinct Substrings【后缀数组】不相同的子串的个数
- SG 函数 hdu1524 & poj 2425 hdu1524 A Chess Game
- 二叉排序树
- Spring Boot AOP实例
- 留言板之公共模块
- 杂谈:vscode的基础功能不足
- SPOJ-694-求字符串中不同子串个数(后缀数组)
- Lightoj1188 Fast Queries(树状数组离线)
- cocos2d 关于retain、release以及autorelease
- 容斥原理1001 HDU 2841
- 非负矩阵分解NMF
- Android实用视图动画及工具系列之四:多状态CheckBox,可设置大小尺寸和设置不可用的复选框
- Linux基础-文件
- TP:728A348E
- 一类数据多种存储(虑将频繁查询的数据加载到内存或者内存数据库。如果一类数据,即要在内存中存储一份,又要在数据库中存储一)