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 ...
随机推荐
- npm WARN network …… request to https://cnpmjs.…… failed, reason: socket hang up
出现类似问题的原因是由于之前配置了镜像导致的 解决方案:删掉镜像,使用npm本身进行安装 删除镜像的命令: 方法1: npm config delete registry 方法2: npm confi ...
- HTTP协议图--HTTP 协议基础
1.通过请求和响应的交换达成通信 应用 HTTP 协议时,必定是一端担任客户端角色,另一端担任服务器端角色.仅从一条通信线路来说,服务器端和客服端的角色是确定的.HTTP 协议规定,请求从客户端发出, ...
- python28 excel读取模块xlrd
安装: pip install xlrd 简单使用: import xlrd book = xlrd.open_workbook(r'C:\Users\dinghanhua\Desktop\yqqap ...
- 通过163smtp服务器向各大邮箱发送邮件(SOCKET编程)
package server; import java.io.*; import java.net.*; import java.sql.Time; import java.util.Scanner; ...
- PostgreSQL 连接问题 FATAL: no pg_hba.conf entry for host
The server doesn't grant access to the database: the server reports FATAL: no pg_hba.conf entry for ...
- GPU性能:光栅化、图层混合、离屏渲染
So, shouldRasterize will not affect the green/red you see using Instruments. In order to have everyt ...
- bzoj4403:序列统计
我好傻啊 题目 先来看看长度只能为\(n\)的情况 那么答案非常显然是\(\binom{m+n-1}{n}\) 其中\(m=R-L+1\) 因为我们要构造一个非降序列,显然可能一个数会被选择多次,组合 ...
- 4、Android-数据存储方案(使用LitePal操作数据库)
4.5.使用LitePal操作数据库 4.5.1.LitePal简介 LitePal是一款开源的Android数据库框架 采用了关系映射(ORM)的模式 将经常使用的一些数据库做了封装 是得不用编写S ...
- Spring(十)之自定义事件
编写自定义事件的简单流程如下: (1)编写CustomEvent.java package com.tutorialspoint; import org.springframework.context ...
- 从零搭建vue
第一步: 安装node.js,一般安装 长期维护版 相对比较稳定 点击下载,下载好了之后双击运行,可选择安装路径,然后一路下一步即可. 安装完成后,在cmd输入 node -v 如果出现版本号,则安 ...