3238: [Ahoi2013]差异 后缀数组+分治+乘法原理
2016-01-11 08:05
267 查看
首先后缀数组似乎就不是正确的姿势?
然后写了后缀数组不写单调栈好像更不是正确的姿势?
反正我是暴力水过了。。
st表预处理出最小值点,每次寻找最小值点然后乘法原理计算两边的乘积。再对左右区间分别处理。6s妥妥水过。
卧槽我后缀数组居然写错了。。调了一早晨都以为是分治写错。。果然不能对自己的后缀数组太自信QAQ。
然后写了后缀数组不写单调栈好像更不是正确的姿势?
反正我是暴力水过了。。
st表预处理出最小值点,每次寻找最小值点然后乘法原理计算两边的乘积。再对左右区间分别处理。6s妥妥水过。
卧槽我后缀数组居然写错了。。调了一早晨都以为是分治写错。。果然不能对自己的后缀数组太自信QAQ。
[code]#include<bits/stdc++.h> #define inf 1000000007 #define ll long long #define N 500005 using namespace std; char s[500005]; int len; ll ans,sum; int t1 ,t2 ,cc ,sa ,rank ,height ; struct node {int v,id;} f [20]; inline bool cmp(int *y,int a,int b,int l) { int arank1=y[a]; int brank1=y[b]; int arank2=a+l>=len?-1:y[a+l]; int brank2=b+l>=len?-1:y[b+l]; return arank1==brank1&&arank2==brank2; } inline void make_sa() { int *x=t1,*y=t2; int m=26; for (int i=0;i<m;i++) cc[i]=0; for (int i=0;i<len;i++) ++cc[x[i]=s[i]-'a']; for (int i=1;i<m;i++) cc[i]+=cc[i-1]; for (int i=len-1;~i;i--) sa[--cc[x[i]]]=i; for (int k=1;k<len;k<<=1) { int p=0; for (int i=len-k;i<len;i++) y[p++]=i; for (int i=0;i<len;i++) if (sa[i]>=k) y[p++]=sa[i]-k; for (int i=0;i<m;i++) cc[i]=0; for (int i=0;i<len;i++) ++cc[x[y[i]]]; for (int i=1;i<m;i++) cc[i]+=cc[i-1]; for (int i=len-1;~i;i--) sa[--cc[x[y[i]]]]=y[i]; swap(x,y); m=1; x[sa[0]]=0; for (int i=1;i<len;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?m-1:m++; if (m>=len) break; } } inline void make_height() { for (int i=0;i<len;i++) rank[sa[i]]=i; int k=0; height[0]=0; for (int i=0;i<len;i++) { if (!rank[i]) continue; int j=sa[rank[i]-1]; if (k) k--; while (s[j+k]==s[i+k]) k++; height[rank[i]]=k; } } inline void make_st() { for (int i=1;i<len;i++) f[i][0]=(node){height[i],i}; f[0][0]=(node){inf,0}; for (int j=1;j<=19;j++) for (int i=0;i<len;i++) if (i+(1<<j)-1<len) { f[i][j]=f[i][j-1]; if (f[i][j].v>f[i+(1<<(j-1))][j-1].v) f[i][j]=f[i+(1<<(j-1))][j-1]; } } inline node ask_min(int l,int r) { int k=log2(r-l+1); if (f[l][k].v<f[r-(1<<k)+1][k].v) return f[l][k]; else return f[r-(1<<k)+1][k]; } void dfs(int l,int r) { if (l>r) return; if (l==r) {sum+=(ll)height[l]; return;} node t=ask_min(l,r); sum+=(ll)(t.id-l+1)*(r-t.id+1)*t.v; dfs(l,t.id-1); dfs(t.id+1,r); } int main() { scanf("%s",s); len=strlen(s); ans=(ll)len*(len-1)*(len+1)/2; make_sa(); make_height(); make_st(); dfs(1,len-1); cout << ans-2*sum; return 0; }
相关文章推荐
- SSH网上商城---用户激活
- SSH网上商城---用户激活
- Wireshark系列之2 路由过程理论分析
- Wireshark系列之2 路由过程理论分析
- 概率图模型(PGM)学习笔记(三)模式判断与概率图流
- SQL Server中的事务日志管理(8/9):优化日志吞吐量
- Search in Rotated Sorted Array
- 162_超大背包问题 (双向搜索)
- 移动端富文本编辑器artEditor
- X.Org 基金会恐将失去其单字母域名:x.org
- 七牛
- 2016成长计划
- OSChina 周一乱弹 —— 为什么活得很累
- MYSQL 事务属性 和 隔离级别
- FB面经prepare: task schedule II
- FB面经prepare: Task Schedule
- 循环引用的问题...
- 家庭经营的目的
- PCB导网表及常见问题处理
- Poj 1743Musical Theme|后缀数组|二分答案