[LGP5115] Check,Check,Check one two!
神奇的思路,还是要学习一个。
题意:给你一个字符串,并定义两个前缀的lcs、两个后缀的lcp,求式子膜\(2^{64}\)的值。
\]
分析:
对于一对存在贡献的\(<i,j>\),咱将它们的lcs、lcp拼起来,可知
s[i-lcs(i,j)]\not=s[j-lcs(i,j)]\\
s[i+lcp(i,j)]\not=s[j+lcp(i,j)]\\
\]
这启发我们找出所有满足下列条件的子串对\(<i,j,len>\)
\]
可以知道它的贡献为
\]
于是考虑建立SA,并记录后缀的前一个字符。
在height数组上从高到低启发式合并,一边统计答案。
#include <bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int N=1e5+10;
int n,k1,k2;
char s[N];
int sa[N],ht[N],rc[N],c[N];
int lp[N],rp[N],bl[N],siz[N],cnt[N][26];
void buildSa() {
int *x=ht,*y=rc,i,p,k,m=128;
for(i=0; i<=m; ++i) c[i]=0;
for(i=1; i<=n; ++i) c[x[i]=s[i]]++;
for(i=1; i<=m; ++i) c[i]+=c[i-1];
for(i=n; i>=1; --i) sa[c[x[i]]--]=i;
for(k=1; k<n; k<<=1) {
for(i=n-k+1,p=0; i<=n; ++i) y[++p]=i;
for(i=1; i<=n; ++i) if(sa[i]>k) y[++p]=sa[i]-k;
for(i=0; i<=m; ++i) c[i]=0;
for(i=1; i<=n; ++i) c[x[y[i]]]++;
for(i=1; i<=m; ++i) c[i]+=c[i-1];
for(i=n; i>=1; --i) sa[c[x[y[i]]]--]=y[i];
swap(x,y), x[sa[1]]=p=1;
for(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((m=p)>=n) break;
}
for(i=1; i<=n; ++i) rc[sa[i]]=i;
for(i=1,k=0; i<=n; ++i) {
p=sa[rc[i]-1]; if(k) k--;
while(s[i+k]==s[p+k]) ++k;
ht[rc[i]]=k;
}
// for(int i=1; i<=n; ++i) {
// cout<<(s+sa[i]);
// if(i>1) cout<<" "<<ht[i];
// cout<<endl;
// }
}
pair<int,int> h[N];
ull sm(int x) {return (ull)x*(x+1)/2;}
ull ssm(int x) {return (ull)x*(2*x+1)*(x+1)/6;}
ull F(int x) {
if(x>=k1+k2) return 0;
ull s1=(ull)(x+1)*sm(min(x,k1))-ssm(min(x,k1));
ull s2=(ull)(x+1)*sm(max(0,x-k2))-ssm(max(0,x-k2));
return s1-s2;
}
ull f[N];
ull calc(int x,int y) {
ull res=(ull)siz[x]*siz[y];
for(int i=0; i<26; ++i) res-=(ull)cnt[x][i]*cnt[y][i];
return res;
}
void merge(int x,int y) {
for(int i=0; i<26; ++i) cnt[y][i]+=cnt[x][i];
for(int i=lp[x]; i<=rp[x]; ++i) bl[i]=y;
lp[y]=min(lp[y],lp[x]);
rp[y]=max(rp[y],rp[x]);
siz[y]+=siz[x];
}
int main() {
scanf("%s%d%d",s+1,&k1,&k2);
n=strlen(s+1);
k1=min(k1,n);
k2=min(k2,n);
for(int i=1; i<=n; ++i) f[i]=F(i);
buildSa();
for(int i=1; i<=n; ++i) {
lp[i]=rp[i]=bl[i]=i; siz[i]=1;
if(sa[i]>1) cnt[i][s[sa[i]-1]-'a']++;
}
for(int i=2; i<=n; ++i)
h[i-1]=make_pair(-ht[i],i);
sort(h+1,h+n);
ull ans=0;
for(int i=1; i<n; ++i) {
int len=-h[i].first;
int x=bl[h[i].second];
int y=bl[h[i].second-1];
if(siz[x]>siz[y]) swap(x,y);
ans+=(ull)f[len]*calc(x,y);
merge(x,y);
// printf("%d,%d,%d,(%llu)\n",len,x,y,ans);
}
printf("%llu\n",ans);
return 0;
}
[LGP5115] Check,Check,Check one two!的更多相关文章
- 烟大 Contest1024 - 《挑战编程》第一章:入门 Problem G: Check The Check(模拟国际象棋)
Problem G: Check The Check Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 10 Solved: 3[Submit][Statu ...
- uva 10196 Check The Check
题目:10196 - Check The Check 思路:水题..模拟 这个代码,前半部分是在数统机房上课的时候写的,挫了点,懒得改了. #include <cstdio> #inclu ...
- UVA - 10196:Check The Check
类型:简单模拟 大致题意:已知国际象棋行棋规则,给你一个局面,问是否将军?谁将谁的军?(保证不会同时将军) 思路:都以小写字母 测试 是否将 大写字母. 然后一个局面测两次(一次直接测,一次反转棋盘, ...
- SQL PRIMARY KEY 约束\SQL FOREIGN KEY 约束\SQL CHECK 约束
SQL PRIMARY KEY 约束 PRIMARY KEY 约束唯一标识数据库表中的每条记录. 主键必须包含唯一的值. 主键列不能包含 NULL 值. 每个表都应该有一个主键,并且每个表只能有一个主 ...
- check约束条件
--约束:对列的值起一个约束性的作用,规定列的值的范围 --主键.外键.非空.自增长标识列.唯一列(unique).check约束 --check 约束 --在某个表里点击右键→设计→进去找到要约束的 ...
- Health Check in eShop -- 解析微软微服务架构Demo(五)
引言 What is the Health Check Health Check(健康状态检查)不仅是对自己应用程序内部检测各个项目之间的健康状态(各项目的运行情况.项目之间的连接情况等),还包括了应 ...
- SQLServer之修改CHECK约束
使用SSMS数据库管理工具修改CHECK约束 1.打开数据库,选择数据表->右键点击->选择设计(或者展开约束,选择约束,右键点击,选择修改,后面步骤相同). 2.选择要修改的数据列-&g ...
- SQL CHECK 约束
SQL CHECK 约束 CHECK 约束用于限制列中的值的范围. 如果对单个列定义 CHECK 约束,那么该列只允许特定的值. 如果对一个表定义 CHECK 约束,那么此约束会在特定的列中对值进行限 ...
- 约束4:唯一约束,Check约束和null
大家知道,关系型数据库的逻辑运算的结果是三值型的,TRUE,FALSE和UNKNOWN,特别是,NULL值和任何值都不相等,任何值和NULL的比较,返回的逻辑结果都是unknown.而NULL值在唯一 ...
- The Singapore NRIC Check Digit
The Singapore NRIC number is made up of 7 digits and a letter behind. This letter is calculated from ...
随机推荐
- 一、MySQL一些简述
概述 数据库(database) : 保存有组织的数据的容器(通常是一个文件或一组文件). 主键(primary key): 唯一标识表中每行的这个列(或这组列)称为主键.主键用表示一个特定的行.没有 ...
- White Sheet
C - White Sheet 思路:先看代码,分成了四个条件.第一个和第二个表示的都是当白矩形存在某个黑矩形内部的情况. 另外就是:白矩形位于两个黑矩形的并集区域. 即可分为两种情况,一种是白矩形位 ...
- JVM之Java类加载机制
什么是类加载机制 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这既是虚拟机的类加载机制 类的生命周期 生命周期简述 ...
- docker之CPU配额参数的混合使用
在启动容器的时候有很多参数,这里来实践一下与CPU相关的参数. 实例: 创建两个容器,docker10.docker20,让两个容器只运行在CPU0上,然后测试CPU使用率. [root@openst ...
- [心得]暑假DAY 5
好久没更新博客了 最近事情太多太多 tarjan进阶,点双边双 T2压力 最大坑点:点双缩点 它不是直接把割点连成树(割点会有环) 而是用割点作”中介“,联接点双构成一颗树(所谓圆方树) 接着在上面进 ...
- 20175215 2018-2019-2 第十周java课程学习总结
第十二章 Java多线程机制 12.1 进程与线程 12.1.1 操作系统与进程 程序是一段静态的代码,它是应用软件执行的蓝本. 进程是程序的一次动态执行过程,它对应了从代码加载.执行至执行完毕的一个 ...
- 【Java面试宝典】正则表达式
文章目录 正则表达式-语法 Pattern.compile方法 ● 请你谈谈Java中是如何支持正则表达式操作的? 考察点:正则表达式 参考回答: Java中的String类提供了支持正则表达式操作的 ...
- mysql解决删除数据后,主键不连续问题
题记:强迫症需求,一个小技巧. 亲测有效 SET @i=; UPDATE table_name SET `); ALTER TABLE table_name AUTO_INCREMENT=; 注意:主 ...
- 加密算法之 MD5算法
题记:本人自测了很多次,该算法和apache的commons utils包中的MD5算法计算一致 一.针对文件内容生成MD5值 应用场景:针对文件,在传输过程由于网络原因丢帧或者被人别恶意篡改内容,可 ...
- flutter shared_preferences 异步变同步
前言 在开发原生iOS或Native应用时,一般有判断上一次安装的版本和当前版本是否是同一个版本,如果不是同一个版本,则要显示引导页,这个过程是把版本号持久化存储起来,在每一次启动时进行判断,这个过程 ...