神奇的思路,还是要学习一个。

题意:给你一个字符串,并定义两个前缀的lcs、两个后缀的lcp,求式子膜\(2^{64}\)的值。

\[\sum_{1\le i<j\le n} lcp(i,j)lcs(i,j)[lcp(i,j)\le k1][lcs(i,j)\le k2]
\]

分析:

对于一对存在贡献的\(<i,j>\),咱将它们的lcs、lcp拼起来,可知

\[s[i-lcs(i,j)+1,i+lcp(i,j)-1]=s[j-lcs(i,j)+1,j+lcp(i,j)-1]\\
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>\)

\[s[i,i+len-1]=s[j,j+len-1],s[i-1]\not=s[j-1],s[i+len]\not=s[j+len]
\]

可以知道它的贡献为

\[\sum_{\max(1,len-k2+1)}^{\min(len,k1)} k(len-k+1)=\sum_{k=1}^{min(len,k1)}k(len-k+1)-\sum_{k=1}^{\max(0,len-k2)}k(len-k+1)
\]

于是考虑建立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!的更多相关文章

  1. 烟大 Contest1024 - 《挑战编程》第一章:入门 Problem G: Check The Check(模拟国际象棋)

    Problem G: Check The Check Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 10  Solved: 3[Submit][Statu ...

  2. uva 10196 Check The Check

    题目:10196 - Check The Check 思路:水题..模拟 这个代码,前半部分是在数统机房上课的时候写的,挫了点,懒得改了. #include <cstdio> #inclu ...

  3. UVA - 10196:Check The Check

    类型:简单模拟 大致题意:已知国际象棋行棋规则,给你一个局面,问是否将军?谁将谁的军?(保证不会同时将军) 思路:都以小写字母 测试 是否将 大写字母. 然后一个局面测两次(一次直接测,一次反转棋盘, ...

  4. SQL PRIMARY KEY 约束\SQL FOREIGN KEY 约束\SQL CHECK 约束

    SQL PRIMARY KEY 约束 PRIMARY KEY 约束唯一标识数据库表中的每条记录. 主键必须包含唯一的值. 主键列不能包含 NULL 值. 每个表都应该有一个主键,并且每个表只能有一个主 ...

  5. check约束条件

    --约束:对列的值起一个约束性的作用,规定列的值的范围 --主键.外键.非空.自增长标识列.唯一列(unique).check约束 --check 约束 --在某个表里点击右键→设计→进去找到要约束的 ...

  6. Health Check in eShop -- 解析微软微服务架构Demo(五)

    引言 What is the Health Check Health Check(健康状态检查)不仅是对自己应用程序内部检测各个项目之间的健康状态(各项目的运行情况.项目之间的连接情况等),还包括了应 ...

  7. SQLServer之修改CHECK约束

    使用SSMS数据库管理工具修改CHECK约束 1.打开数据库,选择数据表->右键点击->选择设计(或者展开约束,选择约束,右键点击,选择修改,后面步骤相同). 2.选择要修改的数据列-&g ...

  8. SQL CHECK 约束

    SQL CHECK 约束 CHECK 约束用于限制列中的值的范围. 如果对单个列定义 CHECK 约束,那么该列只允许特定的值. 如果对一个表定义 CHECK 约束,那么此约束会在特定的列中对值进行限 ...

  9. 约束4:唯一约束,Check约束和null

    大家知道,关系型数据库的逻辑运算的结果是三值型的,TRUE,FALSE和UNKNOWN,特别是,NULL值和任何值都不相等,任何值和NULL的比较,返回的逻辑结果都是unknown.而NULL值在唯一 ...

  10. The Singapore NRIC Check Digit

    The Singapore NRIC number is made up of 7 digits and a letter behind. This letter is calculated from ...

随机推荐

  1. Alpha冲刺(2/6)

    队名:007 组长博客: https://www.cnblogs.com/Linrrui/p/11861798.html 作业博客: https://edu.cnblogs.com/campus/fz ...

  2. Selenium2Library测试web

    Selenium 定位元素 ▲ Locator 可以id或name来用定位界面元素 也可以使用XPath或Dom,但是,必须用XPath=或Dom=来开头 ▲ 最好使用id来定位,强烈建议强制要求开发 ...

  3. DP&图论 DAY 2 下午

    DP&图论  DAY 2  下午 基础树形DP 前言◦ 1:与树或图的生成树相关的动态规划.◦ 2:以每棵子树为子结构,在父亲节点合并,注意树具有天然的子结构.这是很优美的很利于dp的.◦ 3 ...

  4. Carousel 走马灯

    在有限空间内,循环播放同一类型的图片.文字等内容 基础用法 适用广泛的基础用法 结合使用el-carousel和el-carousel-item标签就得到了一个走马灯.幻灯片的内容是任意的,需要放在e ...

  5. [idea]添加jar包的方法

    一:在项目的根目录下建立lib文件夹,然后将对应的jar包文件拷贝进去. 二:点击项目右键,选择Open Module Settings 三.选择Project Settings->Librar ...

  6. 阶段3 3.SpringMVC·_02.参数绑定及自定义类型转换_7 获取Servlet原生的API

    控制器里面获取常用的request对象或者Response对象. 想拿到谁, 就在参数上写上谁 再获取servletConetext并输出

  7. EPOLL内核原理极简图文解读(转)

    预备知识:内核poll钩子原理内核函数poll_wait把当前进程加入到驱动里自定义的等待队列上 当驱动事件就绪后,就可以在驱动里自定义的等待队列上唤醒调用poll的进程 故poll_wait作用:可 ...

  8. Git代码行数统计命令

    统计zhangsan在某个时间段内的git新增删除代码行数 git log --author=zhangsan--since=2018-01-01 --until=2019-04-01 --forma ...

  9. iOS实现渐变颜色

    下面是我的两种实现: 1.直接图片展示,注意图片的变形问题; 2.用CAGradientLayer渐变颜色实现; 代码如下: // // ViewController.m // ImageStrenc ...

  10. shell脚本安装python、pip-----非交互式的--批量执行函数

    首先把pip-.tgz 安装包放在 /usr/local 下面,按照顺序先安装pip,再安装python.不要先安装或只安装python,否则很容易出错, cat >>pip-python ...