【bzoj3238】【AHOI2013】【差异】【后缀数组+单调栈】
2016-06-15 16:06
453 查看
Description
Input
一行,一个字符串SOutput
一行,一个整数,表示所求值
Sample Input
cacaoSample Output
54HINT
2<=N<=500000,S由小写英文字母组成题解:
把式子拆开之后可以发现就是所有后缀长度的n-1倍减去任两个后缀的lcp的长度的两倍.
第一部分直接算即可,第二部分可以用后缀数组.
求出height数组之后对于height[i]找出他前面第一个小于等于它的位置和后面第一个小于它的位置.
这之间的i前面的和i后面的任意两个后缀的lcp长度都是height[i];
扫一遍统计一下即可.
代码:
#include<iostream> #include<cstdio> #include<cstring> #define N 500010 using namespace std; int n,sa ,s ,t1 ,t2 ,rank ,c ,h ,after ,pre ,top,st ; long long ans; char ch ; bool cmp(int *y,int p,int q,int k){ int a=(p+k)>=n?-1:y[p+k]; int b=(q+k)>=n?-1:y[q+k]; return a==b&&y[p]==y[q]; } void build_sa(int m){ int *x=t1,*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]]=cmp(y,sa[i],sa[i-1],k)?p-1:p++; if (p>=n) break; m=p; } } void geth(){ int k(0); for (int i=0;i<n;i++) rank[sa[i]]=i; for (int i=0;i<n;i++){ if (!rank[i]) continue; if (k) k--;int j=sa[rank[i]-1]; while (s[j+k]==s[i+k]) k++; h[rank[i]]=k; } //for (int i=0;i<n;i++) cout<<h[i]<<' '; //cout<<endl; } int main(){ scanf("%s",ch);n=strlen(ch); for (int i=0;i<n;i++) s[i]=ch[i]-'a'+1; build_sa(27);geth(); for (int i=1;i<=n;i++) ans+=i; ans=ans*(long long)(n-1); top=0;pre[1]=0;st[++top]=1; for (int i=2;i<=n-1;i++){ while (top&&h[st[top]]>h[i]) top--; pre[i]=st[top]; st[++top]=i; } top=0;after[n-1]=n;st[++top]=n-1;st[0]=n; for (int i=n-1;i>=1;i--){ while (top&&h[st[top]]>=h[i]) top--; after[i]=st[top]; st[++top]=i; } // for (int i=1;i<n;i++) cout<<pre[i]<<' '<<after[i]<<endl; for (int i=1;i<n;i++) ans=ans-(long long)(after[i]-i)*(i-pre[i])*h[i]*2; cout<<ans<<endl; }
相关文章推荐
- postgressql
- Struts2 配置JSON,记录下
- 在Fragment中OnActivityResult方法中接收Activity中返回的值
- 通过Navicat for MySQL远程连接的时候报错mysql 1130的解决方法
- GitHub README.md 语法
- 剑指offer——二进制中1的个数
- SQLAlchemy 代码学习
- 递归实现1到100的和、10的阶乘(Java语言)
- 5-18 二分法求多项式单根 (用不少人竟然用 浮点数 0.0 == 0 的用法,哎)
- EF5 通用数据层 增删改查操作,泛型类
- mongo VUE的使用(增删改查以及创建索引的非常规办法)
- 枚举与静态final
- ios学习路线—Objective-C(深浅拷贝)
- android 6.0上getResources.getColor遭弃用
- Editplus“替换”中的正则表达式使用
- 怎样用Eclipse进行远程debug
- Python运算符与表达式
- OpenCV中的RANSAC详解
- 关于判断Excel中DEL的行
- android:excludefromRecents属性控制在不在recent列表中显示