【bzoj3238】[Ahoi2013]差异
3238: [Ahoi2013]差异
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 3425 Solved: 1559
[Submit][Status][Discuss]
Description
Input
一行,一个字符串S
Output
一行,一个整数,表示所求值
Sample Input
Sample Output
54
HINT
2<=N<=500000,S由小写英文字母组成
Source
[Submit][Status][Discuss]
这题很尬。。。。。。
我能说我是看错题目才想到这种做法的吗。。?
首先对于那个和式,很容易发现和按sa数组下标的顺序算的答案是一样的
因为把两个式子乘二都等于算所有( i , j )有序対的差异
于是。。我们可以用后缀数组瞎搞。。。
建一下后缀数组,然后从后往前做,维护height的最小值的和即可
单调栈就可以了。。。然而蒟蒻很蠢居然还上了一棵线段树。。。。。。
PS.听说出题的目的是考后缀自动机。。?
代码:
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;typedef long long LL;const int INF = 2147483647;
const int maxn = 500100;
const int maxseg = 4 * maxn;int m;
char s[maxn];
int rank[maxn],t1[maxn],t2[maxn],c[maxn];
LL siz[maxseg],sum[maxseg],ans,n,sa[maxn],sumtj,height[maxn];
bool flag[maxseg];inline void del(int o)
{flag[o] = 1; siz[o] = sum[o] = 0;
}inline void pushdown(int o)
{if (flag[o]){int lc = o * 2,rc = o * 2 + 1;del(lc); del(rc);flag[o] = 0;}
}inline void maintain(int o)
{int lc = o * 2,rc = o * 2 + 1;siz[o] = siz[lc] + siz[rc];sum[o] = sum[lc] + sum[rc];
}inline void reset(int o,int l,int r,int al,int ar)
{if (al <= l && r <= ar){del(o); return;}pushdown(o);int lc = o * 2,rc = o * 2 + 1,mid = l + r >> 1;if (ar <= mid) reset(lc,l,mid,al,ar);if (mid < al) reset(rc,mid + 1,r,al,ar);if (al <= mid && mid < ar){reset(lc,l,mid,al,mid);reset(rc,mid + 1,r,mid + 1,ar);}maintain(o);
}inline LL query(int o,int l,int r,int al,int ar)
{if (al <= l && r <= ar) return siz[o];pushdown(o);int lc = o * 2,rc = o * 2 + 1,mid = l + r >> 1;if (ar <= mid) return query(lc,l,mid,al,ar);if (mid < al) return query(rc,mid + 1,r,al,ar);if (al <= mid && mid < ar) return query(lc,l,mid,al,mid) + query(rc,mid + 1,r,mid + 1,ar);
}inline void inc(int o,int l,int r,int pos,LL cnt)
{if (l == r){sum[o] += cnt * l; siz[o] += cnt; return;}pushdown(o);int mid = l + r >> 1,lc = o * 2,rc = o * 2 + 1;if (pos <= mid) inc(lc,l,mid,pos,cnt);else inc(rc,mid + 1,r,pos,cnt);maintain(o);
}inline void build()
{int *x = t1,*y = t2;for (int i = 1; i <= m; i++) c[i] = 0;for (int i = 1; i <= n; i++) c[x[i] = s[i]]++;for (int i = 1; i <= m; i++) c[i] += c[i - 1];for (int i = n; i >= 1; i--) sa[c[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) y[++p] = sa[i] - k;for (int i = 1; i <= m; i++) c[i] = 0;for (int i = 1; i <= n; i++) c[x[y[i]]]++;for (int i = 1; i <= m; i++) c[i] += c[i - 1];for (int i = n; i >= 1; i--) sa[c[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;int k = 0;for (int i = 1; i <= n; i++){if (k) k--;int j = sa[rank[i] - 1];while (s[i + k] == s[j + k]) k++;height[rank[i]] = k;}
}int main()
{#ifdef dyffreopen("hyj1.txt","r",stdin);freopen("hyj2.txt","w",stdout);#endifscanf("%s",s + 1); n = strlen(s + 1);for (int i = 1; i <= n; i++) m = max(m,(int)s[i]);build();ans = 0;for (LL i = n - 1; i >= 1; i--){sumtj += n - sa[i + 1] + 1;ans += (n - sa[i] + 1) * (n - i) + sumtj;LL k = query(1,0,n,height[i + 1] + 1,n);reset(1,0,n,height[i + 1] + 1,n);inc(1,0,n,height[i + 1],k + 1);ans -= 2 * sum[1];}printf("%lld",ans);return 0;
}
【bzoj3238】[Ahoi2013]差异相关推荐
- BZOJ3238[Ahoi2013]差异
BZOJ3238[Ahoi2013]差异 题目描述 n<=500000n<=500000n,都是小写字母 输入 一行,一个字符串S 输出 一行,一个整数,表示所求值 Solution 公式 ...
- BZOJ3238: [Ahoi2013]差异
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 4840 Solved: 2298 [Submit][Stat ...
- [BZOJ3238] [AHOI2013] 差异 - 后缀自动机
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 1968 Solved: 896 [Submit][Statu ...
- bzoj3238 [Ahoi2013]差异
题目链接 树状数组+单调栈 计算出每个后缀的前面.后面第一个h[]比它小的(前闭后开),乘起来计算答案 1 #include<algorithm> 2 #include<iostre ...
- [BZOJ3238][AHOI2013]差异 [后缀数组+单调栈]
题目地址 - GO-> 题目大意: 给定一个长度为 nn 的字符串SS,令TiTi表示它从第ii个字符开始的后缀,求以下这个式子的值: ∑1≤i<j≤nlen(Ti)+len(Tj)−2× ...
- bzoj3238 [Ahoi2013]差异 后缀自动机
这个题虽然看起来比较麻烦,但其实有一点搞懂了就好做了 每一个后缀的前缀的lcp一定是这个串里的子串, 对于全部子串,如果它不是后缀,那一定可以找到这个串对应的后缀, 而这样的子串和后缀子串是没有区别的 ...
- [BZOJ3238][Ahoi2013]差异
Time Limit: 20 Sec Memory Limit: 512 MB Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Inpu ...
- bzoj3238 [Ahoi2013]差异 后缀自动机
题意:给出一个串,求其中任意两个字串的lcp的总和. 我们可以对于这个串建一颗后缀自动机,实际上,他的parent边树就是一颗后缀树,我们在后缀树上统计答案,设f表示right集合的大小,可以理解为后 ...
- bzoj3238: [Ahoi2013]差异(后缀自动机)
传送门 后缀自动机好题. 题意: 做法:samsamsam 废话 考虑翻转字串,这样后缀的最长公共前缀等于前缀的最长公共后缀. 然后想到parentparentparent树上面两个串的最长公共后缀跟 ...
最新文章
- 习题4-3 求分数序列前N项和 (15 分)
- python天天向上的力量 B
- 剑指offer58-||.左旋转字符串
- 上个ensp实验只发了配置,这次是命令条目
- 打造一款便携版的Sublime Text
- Python3错误和异常
- “HTTPS”安全在哪里?
- LINUX awk操作
- Win11系统中的Thumbs.db文件可以删除吗?
- 论坛源码手机php,【校园社区APP】带后台完整社区论坛手机应用源码
- VMWare安装Win10虚拟机详细教程
- 企业微信有什么用,介绍企业微信6个强大的功能
- thymeleaf中三元运算符嵌套写法
- 首款国产太赫兹成像芯片发布
- 三极管为什么可以放大电流?
- BCI Competition 2008 – Graz dataset A个人翻译(附MATLAB安装BioSig)
- CICE海冰模式的编译
- HTML自定义滚动条附效果图和完整源码
- 一个80后SEOER对于SEO职业规划的三点想法
- 「唇语识别技术」看不透TA的心,但可以听懂TA的话