题目链接

BZOJ3238

题解

简单题

经典后缀数组 + 单调栈套路,求所有后缀\(lcp\)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define cls(s) memset(s,0,sizeof(s))
#define mp(a,b) make_pair<int,int>(a,b)
#define cp pair<int,int>
using namespace std;
const int maxn = 500005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
char s[maxn];
int sa[maxn],rank[maxn],height[maxn],bac[maxn],t1[maxn],t2[maxn],n,m;
void getsa(){
int *x = t1,*y = t2; m = 255;
for (int i = 0; i <= m; i++) bac[i] = 0;
for (int i = 1; i <= n; i++) bac[x[i] = s[i]]++;
for (int i = 1; i <= m; i++) bac[i] += bac[i - 1];
for (int i = n; i; i--) sa[bac[x[i]]--] = i;
for (int k = 1; k <= n; k <<= 1){
int p = 0;
for (int i = n - k + 1; i <= n; i++) y[++p] = i;
for (int i = 1; i <= n; i++) if (sa[i] - k > 0) y[++p] = sa[i] - k;
for (int i = 0; i <= m; i++) bac[i] = 0;
for (int i = 1; i <= n; i++) bac[x[y[i]]]++;
for (int i = 1; i <= m; i++) bac[i] += bac[i - 1];
for (int i = n; i; i--) sa[bac[x[y[i]]]--] = y[i];
swap(x,y);
x[sa[1]] = p = 1;
for (int i = 2; i <= n; i++)
x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p : ++p);
if (p >= n) break;
m = p;
}
for (int i = 1; i <= n; i++) rank[sa[i]] = i;
for (int i = 1,k = 0; i <= n; i++){
if (k) k--;
int j = sa[rank[i] - 1];
while (s[i + k] == s[j + k]) k++;
height[rank[i]] = k;
}
}
cp st[maxn],t;
int top;
void solve(){
LL sum = 0,ans = 0;
for (int i = 2; i <= n; i++){
t = mp(height[i],1);
while (top && st[top].first >= t.first){
sum -= 1ll * st[top].first * st[top].second;
t.second += st[top].second;
top--;
}
st[++top] = t;
sum += 1ll * t.first * t.second;
ans += sum;
}
printf("%lld\n",1ll * n * (n + 1) * (n - 1) / 2 - 2 * ans);
}
int main(){
scanf("%s",s + 1); n = strlen(s + 1);
getsa();
solve();
return 0;
}

最新文章

  1. 洛谷CON1041 NOIP模拟赛一试
  2. EJB 简介
  3. Android 标题栏菜单设置与应用(popupWindow的应用)
  4. 【Mocha.js 101】钩子函数
  5. java 线程演示
  6. IsBackground的理解
  7. LINUX系统编程 由REDIS的持久化机制联想到的子进程退出的相关问题
  8. Array 数组常用方法
  9. php用jquery-ajax上传多张图片限制图片大小
  10. UI Automation 简介
  11. Codeforces Round #137 (Div. 2)
  12. 说说http请求
  13. json、map互转
  14. springmvc.xml或spring.xml 能运行配置文件总是出现错误
  15. 关于springmvc配置validator的注意事项
  16. 【Luogu2711】小行星(网络流,最大流)
  17. iOS 枚举 初体验
  18. Mail.Ru Cup 2018 Round 3
  19. Ubuntu系统修改BIOS时间问题
  20. PHP和Mysql事物处理

热门文章

  1. 牛客小白月赛1 I あなたの蛙が帰っています 【卡特兰数】
  2. CSU1216: 异或最大值(01Trie树)
  3. 【模板时间】◆模板&#183;III◆ 单调子序列
  4. Python——合集
  5. PHP表单安全过滤和防注入 htmlspecialchars() 和test_input()
  6. 1016-06-首页20-封装工具条---UITableView控件距离顶部的间距问题----cell选中时的背景颜色设置
  7. [CodeForces948D]Perfect Security(01字典树)
  8. ABAP 7.51 構文書き方変換について
  9. wlr设置 Blog Ping
  10. 原理剖析-Netty之服务端启动工作原理分析(下)