BZOJ4650/UOJ219 [Noi2016]优秀的拆分
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
Description
Input
Output
Sample Input
aabbbb
cccccc
aabaabaabaa
bbaabaababaaba
Sample Output
5
4
7
explanation
我们用 S[i,j]S[i,j] 表示字符串 SS 第 ii 个字符到第 jj 个字符的子串(从 11 开始计数)。
第一组数据中,共有 33 个子串存在优秀的拆分:
S[1,4]=aabbS[1,4]=aabb,优秀的拆分为 A=aA=a,B=bB=b;
S[3,6]=bbbbS[3,6]=bbbb,优秀的拆分为 A=bA=b,B=bB=b;
S[1,6]=aabbbbS[1,6]=aabbbb,优秀的拆分为 A=aA=a,B=bbB=bb。
而剩下的子串不存在优秀的拆分,所以第一组数据的答案是 33。
第二组数据中,有两类,总共 44 个子串存在优秀的拆分:
对于子串 S[1,4]=S[2,5]=S[3,6]=ccccS[1,4]=S[2,5]=S[3,6]=cccc,它们优秀的拆分相同,均为 A=cA=c,B=cB=c,但由于这些子串位置不同,因此要计算 33 次;
对于子串 S[1,6]=ccccccS[1,6]=cccccc,它优秀的拆分有 22 种:A=cA=c,B=ccB=cc 和 A=ccA=cc,B=cB=c,它们是相同子串的不同拆分,也都要计入答案。
所以第二组数据的答案是 3+2=53+2=5。
第三组数据中,S[1,8]S[1,8] 和 S[4,11]S[4,11] 各有 22 种优秀的拆分,其中 S[1,8]S[1,8] 是问题描述中的例子,所以答案是 2+2=42+2=4。
第四组数据中,S[1,4]S[1,4],S[6,11]S[6,11],S[7,12]S[7,12],S[2,11]S[2,11],S[1,8]S[1,8] 各有 11 种优秀的拆分,S[3,14]S[3,14] 有 22 种优秀的拆分,所以答案是 5+2=75+2=7。
- //It is made by ljh2000
- #include <iostream>
- #include <cstdlib>
- #include <cstring>
- #include <cstdio>
- #include <cmath>
- #include <algorithm>
- #include <ctime>
- #include <vector>
- #include <queue>
- #include <map>
- #include <set>
- #include <string>
- #include <complex>
- using namespace std;
- typedef long long LL;
- const int MAXN = 50011;
- const int MOD = 30000007;
- int n;
- char ch[MAXN];
- LL hash[MAXN],mo[MAXN],u[MAXN],v[MAXN],ans;
- //u[i]记录i开头的AA的方案数,v[i]记录i结尾的AA的方案数,均为差分数组
- inline int getint(){
- int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
- if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
- }
- inline LL gethash(int l,int r){
- LL now=hash[l]-hash[r]*mo[r-l];
- now%=MOD; now+=MOD; now%=MOD;
- return now;
- }
- inline void work(){
- int T=getint(); mo[0]=1; for(int i=1;i<=30000;i++) mo[i]=mo[i-1]*31,mo[i]%=MOD;
- while(T--) {
- scanf("%s",ch+1); n=strlen(ch+1); int l,r,mid,head,tail,last,pos;
- memset(u,0,sizeof(u)); memset(v,0,sizeof(v));
- hash[n+1]=0; for(int i=n;i>=1;i--) hash[i]=hash[i+1]*31+ch[i]-'a'+1,hash[i]%=MOD;
- for(int L=1;L*2<=n;L++)//枚举一个A的长度,则AA长度为2*L
- for(int i=L+L;i<=n;i+=L) { //和后面的块求lcp,和前面的块求lcs
- if(ch[i]!=ch[i-L]) continue;
- //lcs
- l=1; r=L; last=i-L; pos=0;
- while(l<=r) {
- mid=(l+r)>>1;
- if(gethash(last-mid+1,last+1)==gethash(i-mid+1,i+1)) l=mid+1,pos=mid;
- else r=mid-1;
- }
- head=i-pos+1;
- //lcp
- l=1; r=L; pos=0;
- while(l<=r){
- mid=(l+r)>>1;
- if(gethash(last,last+mid)==gethash(i,i+mid)) l=mid+1,pos=mid;
- else r=mid-1;
- }
- tail=i+pos-1;
- head=max(head+L-1,i);
- tail=min(tail,i+L-1);
- if(head<=tail) {
- u[head-L*2+1]++; u[tail+1-L*2+1]--;
- v[head]++; v[tail+1]--;
- }
- }
- ans=0;
- for(int i=1;i<=n;i++) u[i]+=u[i-1],v[i]+=v[i-1];
- for(int i=1;i<n;i++) ans+=v[i]*u[i+1];
- printf("%lld\n",ans);
- }
- }
- int main()
- {
- work();
- return 0;
- }
BZOJ4650/UOJ219 [Noi2016]优秀的拆分的更多相关文章
- BZOJ4650:[NOI2016]优秀的拆分——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4650 https://www.luogu.org/problemnew/show/P1117 如果 ...
- 【BZOJ4650】[NOI2016] 优秀的拆分(后缀数组)
点此看题面 大致题意: 定义将一个字符串拆成\(AABB\)的形式为优秀拆分,求一个字符串所有子串的优秀拆分个数. 后缀数组 这题可是一道后缀数组黑题啊. 其实看完题解这题还是挺简单的. 大致思路 显 ...
- UOJ219 NOI2016 优秀的拆分 二分、字符串哈希
传送门 题目可以转化为求\(AA\)的数量,设\(cnt1_x\)表示左端点为\(x\)的\(AA\)的数量,\(cnt2_x\)表示右端点为\(x\)的\(AA\)的数量,那么答案就是\(\sum ...
- 【BZOJ4650&UOJ219】优秀的拆分(二分,hash)
题意: 思路: 在实现时SA可以用hash+二分代替,会多一个log BZ上跑的飞快,但UOJ上extra卡出翔,已经放弃 不过转C或者写SA没准就过了 看来转C迫在眉睫 ; ..]of int64; ...
- [UOJ#219][BZOJ4650][Noi2016]优秀的拆分
[UOJ#219][BZOJ4650][Noi2016]优秀的拆分 试题描述 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 A 和 B 是任意非空字符串,则我们称该字符串的这种拆分是优秀 ...
- [NOI2016]优秀的拆分&&BZOJ2119股市的预测
[NOI2016]优秀的拆分 https://www.lydsy.com/JudgeOnline/problem.php?id=4650 题解 如果我们能够统计出一个数组a,一个数组b,a[i]表示以 ...
- luogu1117 [NOI2016]优秀的拆分
luogu1117 [NOI2016]优秀的拆分 https://www.luogu.org/problemnew/show/P1117 后缀数组我忘了. 此题哈希可解决95分(= =) 设\(l_i ...
- 【BZOJ4560】[NOI2016]优秀的拆分
[BZOJ4560][NOI2016]优秀的拆分 题面 bzoj 洛谷 题解 考虑一个形如\(AABB\)的串是由两个形如\(AA\)的串拼起来的 那么我们设 \(f[i]\):以位置\(i\)为结尾 ...
- [NOI2016]优秀的拆分(SA数组)
[NOI2016]优秀的拆分 题目描述 如果一个字符串可以被拆分为 \(AABB\) 的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 \(aabaaba ...
随机推荐
- UML中关系的分类及其概念——总结备忘
UML中关系分类: 依赖:依赖是两个事物间的语义关系,其中一个事物(独立事物)发生变化会影响另一个事物(依赖事物)的语义. 关联:关联是类与类之间的联接,它使一个类知道另一类的属性和方法. 聚合:聚合 ...
- 「小程序JAVA实战」微信小程序简介(一)
转自:https://idig8.com/2018/08/09/xiaochengxu-chuji-01/ 一直想学习小程序,苦于比较忙,加班比较多没时间,其实这都是理由,很多时候习惯了搬砖,习惯了固 ...
- 通过helloworld来认识下backbone
Backbone主要涉及3部分:model,collection和view.而这个框架的优势在于:数据与视图分离,通过操作model来自动更新view. 根据我的个人经验,直接写个简单的例子是最最直观 ...
- Python常用算法
本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机 ...
- UIAtlas
[UIAtlas] UIAtlas is a container that has coordinate information for a bunch of sprites. AtlasType有2 ...
- xcode找回欢迎界面
[xcode找回欢迎界面] 有一次嫌xcode界面烦,点击了以下checkbox取消了欢迎界面: 随后发现没了欢迎界面反而更不方便,一心想找回欢迎界面,Preference里找了半天没找到开关,原来开 ...
- CronTrigger表达式和Quartz使用实例入门
CronTriggers往往比SimpleTrigger更有用,如果您需要基于日历的概念,而非SimpleTrigger完全指定的时间间隔,如每月8日发工资的定时任务. CronTrigger,你可以 ...
- codeforce452DIV2——F. Letters Removing
题意:给一个字符串和m个操作,每次给出l,r,c,把字符串中l-r这段区间的字符为c的字符删掉,求最后的字符串.(n,m<=2e5)线段树.注意这个区间修改和普通区间修改的区别. 他们都是用树状 ...
- 【CF#338D】GCD Table
[题目描述] 有一张N,M<=10^12的表格,i行j列的元素是gcd(i,j) 读入一个长度不超过10^4,元素不超过10^12的序列a[1..k],问是否在某一行中出现过 [题解] 要保证g ...
- CMake 自定义编译选项
自定义编译选项 CMake 允许为项目增加编译选项,从而可以根据用户的环境和需求选择最合适的编译方案. 例如,可以将 MathFunctions 库设为一个可选库,如果该选项为 ON ,就使用该库定义 ...