Codeforces #123D: 后缀数组+单调栈
You are given a string s. Each pair of numbers l and r that fulfill the condition 1 ≤ l ≤ r ≤ |s|, correspond to a substring of the string s, starting in the position l and ending in the position r (inclusive).
Let's define the function of two strings F(x, y) like this. We'll find a list of such pairs of numbers for which the corresponding substrings of string x are equal to string y. Let's sort this list of pairs according to the pair's first number's increasing. The value of function F(x, y)equals the number of non-empty continuous sequences in the list.
For example: F(babbabbababbab, babb) = 6. The list of pairs is as follows:
(1, 4), (4, 7), (9, 12)
Its continuous sequences are:
- (1, 4)
- (4, 7)
- (9, 12)
- (1, 4), (4, 7)
- (4, 7), (9, 12)
- (1, 4), (4, 7), (9, 12)
Your task is to calculate for the given string s the sum F(s, x) for all x, that x belongs to the set of all substrings of a string s.
The only line contains the given string s, consisting only of small Latin letters (1 ≤ |s| ≤ 105).
Print the single number — the sought sum.
Please do not use the %lld specificator to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specificator.
aaaa
20
abcdef
21
abacabadabacaba
188
In the first sample the function values at x equal to "a", "aa", "aaa" and "aaaa" equal 10, 6, 3 and 1 correspondingly.
In the second sample for any satisfying x the function value is 1.
题意:如果某一种子串s在原串中出现了k次,根据题目定义的函数,它产生的贡献是(k+1)*k/2
这个条件很奇怪,我们尝试转化模型,就会发现这个函数相当于我们将这k个s串排成一排,每个
串和它自己以及后面的串匹配一次,总次数就是题目要求的函数
于是我们可以上后缀数组+高度数组,对于每一个后缀,和后面的每一个后缀的算一个最长公共前缀,然后根据长度统计答案
这个东西可以用单调栈搞一搞,最后每个后缀和自己可以匹配一次,也就是说如果读入的串长度为n,ans+=(n+1)*n/2
代码:
//#include"bits/stdc++.h"
#include"cstdio"
#include"map"
#include"set"
#include"cmath"
#include"queue"
#include"vector"
#include"string"
#include"ctime"
#include"stack"
#include"deque"
#include"cstdlib"
#include"cstring"
#include"iostream"
#include"algorithm" #define db double
#define ll long long
#define vec vector<ll>
#define Mt vector<vec>
#define ci(x) scanf("%d",&x)
#define cd(x) scanf("%lf",&x)
#define cl(x) scanf("%lld",&x)
#define pi(x) printf("%d\n",x)
#define pd(x) printf("%f\n",x)
#define pl(x) printf("%lld\n",x)
//#define rep(i, x, y) for(int i=x;i<y;i++)
#define rep(i, n) for(int i=0;i<n;i++)
using namespace std;
const int N = 1e6 + ;
const int mod = 1e9 + ;
const int MOD = mod - ;
const int inf = 0x3f3f3f3f;
const db PI = acos(-1.0);
const db eps = 1e-;
int sa[N];
int rk[N];
int tmp[N];
int lcp[N];
int n,k;
bool cmp(int i,int j){
if(rk[i] != rk[j]) return rk[i]<rk[j];
else
{
int ri=i+k<=n?rk[i+k]:-;
int rj=j+k<=n?rk[j+k]:-;
return ri<rj;
}
}
void bulid(string s,int *sa)
{
n=(int)s.size();
for(int i=;i<=n;i++){
sa[i]=i;
rk[i]=i<n?s[i]:-;
}
for(k=;k<=n;k*=){
sort(sa,sa+n+,cmp);
tmp[sa[]]=;
for(int i=;i<=n;i++){
tmp[sa[i]]=tmp[sa[i-]]+(cmp(sa[i-],sa[i])?:);
}
for(int i=;i<=n;i++){
rk[i]=tmp[i];
}
}
}
void LCP(string s,int *sa,int *lcp){
n=(int)s.size();
for(int i=;i<=n;i++) rk[sa[i]]=i;
int h=;
lcp[]=;
for(int i=;i<n;i++){
int j=sa[rk[i]-];
for (h ? h-- : ; j + h < n&&i + h < n&&s[j + h] == s[i + h]; h++);
lcp[rk[i]-] = h;
}
}
#define x first
#define y second
#define Pair pair<int,int>
#define mp make_pair stack<Pair> sta;
int main ()
{
string s;
cin>>s;
n=s.length();
bulid(s,sa);
LCP(s,sa,lcp);
ll ans=(ll)n*(ll)(n+)/;
ll cnt=;
for (int i=;i<=n;i++)
{
Pair ins=mp(lcp[i],);//贡献为lcp[i]*num
while (!sta.empty() && sta.top().x>ins.x)
{
cnt-=(ll)sta.top().x*sta.top().y;
ins.y+=sta.top().y;
sta.pop();
}
cnt+=(ll)ins.x*ins.y;
sta.push(ins);
ans+=cnt;
}
cout<<ans<<endl;
return ;
}
Codeforces #123D: 后缀数组+单调栈的更多相关文章
- 【BZOJ-3238】差异 后缀数组 + 单调栈
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1561 Solved: 734[Submit][Status] ...
- BZOJ_3879_SvT_后缀数组+单调栈
BZOJ_3879_SvT_后缀数组+单调栈 Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个 ...
- BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈
BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...
- BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)
BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...
- 【BZOJ3879】SvT 后缀数组+单调栈
[BZOJ3879]SvT Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干 ...
- BZOJ3238 [Ahoi2013]差异 【后缀数组 + 单调栈】
题目链接 BZOJ3238 题解 简单题 经典后缀数组 + 单调栈套路,求所有后缀\(lcp\) #include<iostream> #include<cstdio> #in ...
- BZOJ4199 [Noi2015]品酒大会 【后缀数组 + 单调栈 + ST表】
题目 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品 酒家"和"首席猎手"两个奖项,吸 ...
- poj 3415 Common Substrings 后缀数组+单调栈
题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...
- poj 3415 Common Substrings(后缀数组+单调栈)
http://poj.org/problem?id=3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K Total Sub ...
随机推荐
- Java实例---简单的上课管理系统
源码分析 Course.java package com.ftl.many2many; import java.util.*; public class Course { private int cr ...
- 编码学习---代码OJ网站
代码OJ网站: https://leetcode-cn.com/accounts/login/
- Linux 基础学习大考核
0.关于Linux的简介 Linux(好又免费)的组成部分: Linux 是一种计算机操作系统: 一系列能让您与计算机进行交互操作并运行其它程序的程序. 操作系统由多种基础程序构成.它们使计算机可以与 ...
- 【心得体会】我考完MOS我明白了…
[心得体会]我考完MOS我明白了… 原创 2017-11-10 MSP-李桑榆 MSPrecious成长荟 MOS备考 这篇文章写给还没有考或者准备考MOS的同学 网上有很多介绍MOS考试的 http ...
- Python运算符和数据类型
一.Python的逻辑运算符 1.数字运算符: 运算符 描述 例子 + 加 - 两个对象相加 a + b 输出结果 30 - 减 - 得到负数或是一个数减去另一个数 a - b 输出结果 -10 * ...
- Vuex、Flux、Redux、Redux-saga、Dva、MobX
https://www.jqhtml.com/23003.html 这篇文章试着聊明白这一堆看起来挺复杂的东西.在聊之前,大家要始终记得一句话:一切前端概念,都是纸老虎. 不管是Vue,还是 Reac ...
- BZOJ4008:[HNOI2015]亚瑟王(DP,概率期望)
Description 小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑. 他决定,在脱坑之前,最后再来打一盘亚瑟王.既然是最后一战,就一定要打得漂亮.众所周知,亚瑟王是一个 ...
- BZOJ2208:[JSOI2010]连通数(DFS)
Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示无边. Output 输出一行一个整数,表示该图 ...
- HttpURLConnection与HttpClient学习
转载HttpURLConnection与HttpClient浅析 一.HttpURLConnection的使用 import org.slf4j.Logger; import org.slf4j.Lo ...
- ThinkPHP5入门(一)----框架篇
一.命名规范: 下划线法: 函数的命名 配置参数 常量(大写) 数据表和字段 驼峰法: 属性的命名 方法的命名 帕斯卡法: 类名 类文件名 类的命名