P1117 [NOI2016] 优秀的拆分

news/2025/1/27 13:31:11/文章来源:https://www.cnblogs.com/dcytrl/p/18692555

题意

定义长为 \(2n\) 的字符串 \(s\) 为“双串”当且仅当 \(s_{1\cdots n}=s_{n+1\cdots 2n}\)

定义字符串 \(s\) 的“优秀的拆分”为将该字符串分成两部分,每部分非空且都为双串。一个字符串可能有 0 种或多种优秀的拆分。

对于给定字符串 \(s\) 的所有子串求优秀的拆分数量之和。多组数据。

\(T\le 10,n\le 3\times10^4\)

分析

考虑拆贡献,设 \(a_i\) 为以 \(i\) 结尾的双串数量,\(b_i\) 为以 \(i\) 开头的双串数量,则答案就是 \(\sum_{i=1}^{n-1} a_ib_{i+1}\)

问题在于求 \(a_i,b_i\)。考虑枚举长度 \(len\) 表示双串的长度为 \(2len\),考虑每隔 \(len\) 的长度设立一个观察点,那么一个合法双串一定会恰好覆盖两个观察点,且这两个观察点相邻。

考虑每一对相邻的观察点的贡献,那么我们只需要求出从观察点起向左最多能延伸多少,向右能延伸多少即可。这显然跟以两个观察点为起始的 lcp 和 lcs 有关。

首先,这两个东西 SA 或者二分哈希随便做。其次,不难发现若 \(lcp+lcs\le len\),则这一堆观察点没有贡献。否则,观察点向左延伸最多能延伸 \(lcs\),最少要延伸 \(len-lcp+1\),给这段区间内的 \(a\) 区间 +1,向右延伸也是同理,最少延伸 \(len-lcs+1\),最多延伸 \(lcp\)。区间加可以差分。注意 lcp 和 lcs 都要对 \(len\) 取 min。

不难发现相邻观察点数量和是调和级数,故复杂度 \(O(Tn\log n)\) 或者 \(O(Tn\log^2n)\)。后者需要卡常,但双模换单模就能过。

点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<map>
#include<unordered_map>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
#include<set>
#include<ctime>
#include<random>
#include<cassert>
#define x1 xx1
#define y1 yy1
#define IOS ios::sync_with_stdio(false)
#define ITIE cin.tie(0);
#define OTIE cout.tie(0);
#define PY puts("Yes")
#define PN puts("No")
#define PW puts("-1")
#define P0 puts("0")
#define P__ puts("")
#define PU puts("--------------------")
#define mp make_pair
#define fi first
#define se second
#define gc getchar
#define pc putchar
#define pb emplace_back
#define un using namespace
#define il inline
#define all(x) x.begin(),x.end()
#define mem(x,y) memset(x,y,sizeof x)
#define popc __builtin_popcountll
#define rep(a,b,c) for(int a=(b);a<=(c);++a)
#define per(a,b,c) for(int a=(b);a>=(c);--a)
#define reprange(a,b,c,d) for(int a=(b);a<=(c);a+=(d))
#define perrange(a,b,c,d) for(int a=(b);a>=(c);a-=(d))
#define graph(i,j,k,l) for(int i=k[j];i;i=l[i].nxt)
#define lowbit(x) ((x)&-(x))
#define lson(x) ((x)<<1)
#define rson(x) ((x)<<1|1)
//#define double long double
//#define int long long
//#define int __int128
using namespace std;
using i64=long long;
using u64=unsigned long long;
using pii=pair<int,int>;
template<typename T1,typename T2>inline void ckmx(T1 &x,T2 y){x=x>y?x:y;}
template<typename T1,typename T2>inline void ckmn(T1 &x,T2 y){x=x<y?x:y;}
inline auto rd(){int qwqx=0,qwqf=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')qwqf=-1;ch=getchar();}while(ch>='0'&&ch<='9'){qwqx=(qwqx<<1)+(qwqx<<3)+ch-48;ch=getchar();}return qwqx*qwqf;
}
template<typename T>inline void write(T qwqx,char ch='\n'){if(qwqx<0){qwqx=-qwqx;putchar('-');}int qwqy=0;char qwqz[40];while(qwqx||!qwqy){qwqz[qwqy++]=qwqx%10+48;qwqx/=10;}while(qwqy--)putchar(qwqz[qwqy]);if(ch)putchar(ch);
}
bool Mbg;
const int maxn=3e4+5,inf=0x3f3f3f3f;
const int mod=998244353,base=131;
const long long llinf=0x3f3f3f3f3f3f3f3f;
int n;
char s[maxn];
int a[maxn],b[maxn];
void upd_a(int l,int r){a[l]++,a[r+1]--;}
void upd_b(int l,int r){b[l]++,b[r+1]--;}
int f[maxn],mi[maxn];
int gash(int l,int r){return (f[r]-1ll*f[l-1]*mi[r-l+1]%mod+mod)%mod;
}
int len;
int lcp(int x,int y){int l=1,r=min(len,x),res=0;while(l<=r){int mid=(l+r)>>1;if(gash(x-mid+1,x)==gash(y-mid+1,y))res=mid,l=mid+1;else r=mid-1;;}return res;
}
int lcs(int x,int y){int l=1,r=min(len,n-y+1),res=0;while(l<=r){int mid=(l+r)>>1;if(gash(x,x+mid-1)==gash(y,y+mid-1))res=mid,l=mid+1;else r=mid-1;}return res;
}
inline void solve_the_problem(){scanf("%s",s+1),n=strlen(s+1);mi[0]=1;rep(i,1,n)mi[i]=1ll*mi[i-1]*base%mod,f[i]=(1ll*f[i-1]*base%mod+s[i])%mod;rep(i,1,n)a[i]=b[i]=0;for(len=1;len<=(n>>1);++len){rep(i,1,n/len-1){int p1=min(len,lcp(i*len,(i+1)*len)),p2=min(len,lcs(i*len,(i+1)*len));
//			printf("%d %d %d %d\n",i*len,(i+1)*len,p1,p2);if(p1+p2<=len)continue;upd_b(i*len-p1+1,(i-1)*len+p2),upd_a((i+2)*len-p1,(i+1)*len+p2-1);}}rep(i,1,n)a[i]+=a[i-1],b[i]+=b[i-1];
//	rep(i,1,n)write(a[i],32);P__;i64 ans=0;rep(i,1,n-1)ans+=1ll*a[i]*b[i+1];write(ans);
}
bool Med;
signed main(){
//	freopen("P1117_13.in","r",stdin);freopen("out.out","w",stdout);fprintf(stderr,"%.3lfMB\n",(&Mbg-&Med)/1048576.0);int _=rd();while(_--)solve_the_problem();
}
/**/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/876222.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 中 如何将time命令输出的时间信息保存在文件中

001、 通常做法[root@localhost test]# time seq 10 > a.txt 2> xxx ## 完全追加至xxxreal 0m0.002s user 0m0.000s sys 0m0.002s [root@localhost test]# ls a.txt xxx [root@localhost test]# cat a.txt 1 2 3 4 5 6 7 8 9 10 [root@localhost test]# c…

ABCDE:一个使用Kotlin编写的OpenHarmony逆向工具包

ABCDE是一个使用Kotlin编写的OpenHarmony逆向工具包,目前已经实现的功能为解析方舟字节码文件中 的类信息、方法信息、字面量数组信息以及对方法进行反汇编,解析资源索引文件等功能。 该工具核心功能由纯kotlin(jvm)实现,因此可以提供平台无关的jar包供java工程引用并二次…

【Linux性能】Linux系统中进程运行时间的五大精准检测法

在Linux操作系统的复杂而精细的运行环境中,准确了解各个进程的运行时间对于系统管理员和开发人员而言至关重要。这不仅有助于监控系统性能,还能为调试问题提供关键线索,进而实现对系统资源的高效管理。本文将深入探讨五种在Linux中检查进程运行时间的有效方法,每种方法都具…

VS Code 报错 __float128 is not supported on this target 解决方法

最近在使用 VS Code 时,每一个 cpp 文件都会有如下报错:在中文互联网上并没有搜索到很好的解决方案,但是在 stack overflow 上找到了一个比较好的回答:This problem may be caused by your VSCode using clang-tidy as the C/C++ extension. clang-tidy does not support _…

A Critique of ANSI SQL Isolation Levels.18687395

原文:A critique of ANSI SQL isolation levels摘要:ANSI SQL-92[MS, ANSI]使用脏读、不可重复读以及幻读现象(phenomena)定义了隔离级,本论文展示了这些现象,以及ANSI SQL定义并无法合适的描述众多流行的隔离级别,包括(ANSI标准)所涵盖的级别的标准锁实现。我们还介绍…

0127人工智能创新型教师培育计划(第一期) 试题

# 试题 http://site01.openhydra.net:30012/evt/uploadcode人工智能创新型教师培育计划(第一期)​ 【活动进展每日更新1月26日】​活动更新(1月26日 22:00更新): Python作业​教师AI基础考核作业(见下面介绍),或者可以下载word文件 查看。 1月31日中午24:00前提交, 作…

.net core 使用账号密码方式读取SharePoint 文件(记录)

项目环境 .net 6.0 原代码 是.netframework 4.6 原代码引用了Microsoft.SharePoint.Client 包去操作.其中身份验证的使用的是 SharePointOnlineCredentials 类.但迁移到.net 6,0 后发现这个类已经被移除.测试了常用 的各种方式,大部分均返回403 解决方案: 使用包 dotnet add…

mkcert生成ssl证书+nginx部署局域网内的https服务访问

环境 使用的是树莓派 安装的是ubuntu 系统 https://github.com/FiloSottile/mkcert/releases 下载 添加权限 chmod 777 ./mkcert-v1.4.4-linux-arm64 1、CA 证书加入本地可信 CA ./mkcert-v1.4.4-linux-arm64 -install 2、生成自签证书 ./mkcert-v1.4.4-linux-arm64 …

iPhone 拍摄 LED 灯带视频时候如何防频闪 All In One

iPhone 拍摄 LED 灯带视频时候如何防频闪 All In One 闪动频率不一致 bug? 60Hz 50HziPhone 拍摄 LED 灯带视频时候如何防频闪 All In One闪动频率不一致 bug?60Hz 50Hz errorshttps://www.bilibili.com/video/BV1F5fkY6ERS/ 问题分析 灯的问题,灯在闪。 交流电是 50Hz(中国…

iPhone 视频拍摄 LED 灯带时候如何防频闪 All In One

iPhone 视频拍摄 LED 灯带时候如何防频闪 All In One 闪动频率不一致 bug? 60Hz 50HziPhone 视频拍摄 LED 灯带时候如何防频闪 All In One闪动频率不一致 bug?60Hz 50Hz errorshttps://www.bilibili.com/video/BV1F5fkY6ERS/ solutions demos(🐞 反爬虫测试!打击盗版⚠️)…