题面

洛谷P7114 字符串匹配

\(T\) 组测试数据。给定字符串 \(S\),问有多少不同的非空字符串 \(A\),\(B\),\(C\) 满足 \(S=ABABAB...ABC\) 且 \(A\) 中出现奇数次的字符数不多于 \(C\)。

数据范围:\(1\le T\le 5\),\(1\le |S|\le 2^{20}\)。


这估计是我场上唯一做出来的题目了,NOIP2020 游记 也不放洛谷博客里了。


提供一个 \(\Theta(n)\) 的做法,下标从 \(0\) 开始。

求出 \(S\) 的 Z 数组,\(ze_i\) 表示满足 \(s[0,ze_i)=s[i,i+ze_i)\) 的最大值。

根据 \(s[0,ze_i)=s[i,i+ze_i)\) 可以推出 \(s[i,ze_i)=s[2i,i+ze_i)\)。

所以可以枚举 \(AB\) 的长度 \(i\),易得这个串在前缀重复了 \(\lfloor\frac{ze_i}{i}\rfloor+1\) 次。

然后解决关于出现奇数次的字符的限制。

维护一个树状数组,表示每个 \(j<i\) 的前缀出现奇数次字符数的集合。

计算前缀出现奇数次字符数可以 \(\Theta(1)\),值域为字符集的树状数组时间复杂度也是 \(\Theta(1)\) 的。

考虑对于当前的所有 \(ABAB...AB\) 对应的 \(C\) 中出现奇数次字符数:只有两种可能。

一种是当前后缀出现奇数次字符数,一种是全局出现奇数次字符数。先预处理后者,前者可以 \(\Theta(1)\) 维护。

因为 \(ABAB\) 中出现奇数次字符数肯定为 \(0\),所以对于 \(\lfloor\frac {\lfloor\frac{ze_i}{i}\rfloor+1}{2}\rfloor\) 的肯定是全局次数,\(\lceil\frac {\lfloor\frac{ze_i}{i}\rfloor+1}{2}\rceil\) 的肯定是后缀次数。

然后对于两种情况,答案加上树状数组查询前缀满足条件的 \(A\) 的数量乘以出现次数即可。

所以总时间复杂度 \(\Theta(n)\)。


代码

回家手敲的。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define x first
#define y second
#define bg begin()
#define ed end()
#define pb push_back
#define mp make_pair
#define sz(a) int((a).size())
#define R(i,n) for(int i(0);i<(n);++i)
#define L(i,n) for(int i((n)-1);i>=0;--i)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f; //Data
const int N=1<<20,C=26;
int n,all,last,now,tot[C],cnt[C];
string str; //FenwickTree
int fen[C|1];
void add(int i,int v){for(;i<C+1;i|=i+1) fen[i]+=v;}
int sum(int i,int v=0){for(;i>=0;(i&=i+1)--) v+=fen[i]; return v;} //Zebra
int ze[N];
void zebra(){
int l=0;
R(i,n) ze[i]=0;
R(i,n)if(i){
if(l+ze[l]>i) ze[i]=min(l+ze[l]-i,ze[i-l]);
while(i+ze[i]<n&&str[ze[i]]==str[i+ze[i]]) ze[i]++;
if(i+ze[i]>l+ze[l]) l=i;
}
} //Main
void Main(){
cin>>str,n=sz(str),zebra();
R(i,n)if(i+ze[i]==n) ze[i]--;
ll ns=all=last=now=fen[C]=0;
R(c,C) tot[c]=cnt[c]=fen[c]=0;
R(i,n) tot[str[i]-'a']++;
R(c,C) all+=(tot[c]&1); last=all;
R(i,n){
if(tot[str[i]-'a']&1) last--; else last++;
if(cnt[str[i]-'a']&1) now--; else now++;
tot[str[i]-'a']--,cnt[str[i]-'a']++;
if(i&&i<n-1){
int t=ze[i+1]/(i+1)+1;
// cout<<"i="<<i<<" t="<<t<<'\n';
ns+=1ll*(t/2)*sum(all)+1ll*(t-t/2)*sum(last);
}
// cout<<"now="<<now<<" last="<<last<<" all="<<all<<'\n';
add(now,1);
}
cout<<ns<<'\n';
}
int main(){
//freopen("string.in","r",stdin);
//freopen("string.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int T; cin>>T;
while(T--) Main();
return 0;
}

祝大家学习愉快!

题解-洛谷P7114 字符串匹配的更多相关文章

  1. 洛谷P3375KMP字符串匹配

    传送门 #include <iostream> #include <cstdio> #include <cstring> #include <algorith ...

  2. 洛谷 P1032 字符变换

    洛谷 P1032 字符变换 题目描述 已知有两个字串 A,B 及一组字串变换的规则(至多 6 个规则): A1​ -> B1​ A2​ -> B2​ 规则的含义为:在 A 中的子串 A1​ ...

  3. 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)

    题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...

  4. 题解-洛谷P5217 贫穷

    洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ...

  5. 题解 洛谷P5018【对称二叉树】(noip2018T4)

    \(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...

  6. 题解 洛谷 P3396 【哈希冲突】(根号分治)

    根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...

  7. 题解-洛谷P4229 某位歌姬的故事

    题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...

  8. 题解-洛谷P4724 【模板】三维凸包

    洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...

  9. 题解-洛谷P4859 已经没有什么好害怕的了

    洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...

随机推荐

  1. nginx&http 第三章 ngx 事件event epoll 处理

    1. epoll模块命令集 ngx_epoll_commands  epoll模块上下文 ngx_epoll_module_ctx  epoll模块配置 ngx_epoll_module static ...

  2. Python_入门第一篇【持续更新...】

    1.准备 准备电脑 和 分区 1.准备配置稍高的电脑(后后期需要装虚拟机),分辨率1920*1080 2.分区: C→系统 D→Project E→软件安装盘 F→其他 准备编辑器 1.Sublime ...

  3. Java面试必会-微服务权限认证

    微服务身份认证方案 1. 单点登录(SSO) 这种方案意味着每个面向用户的服务都必须与认证服务交互,这会产生大量非常琐碎的网络流量和重复的工作,当动辄数十个微应用时,这种方案的弊端会更加明显. 2. ...

  4. C#高级编程之反射

    反射的定义 MSDN定义:反射提供描述程序集.模块和类型的对象(Type类型). 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型,然后调用其方法或访问器字段和属性. 如 ...

  5. python多线程——如何停止一个死循环的线程

    进程想要执行任务就需要依赖线程.换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程. 那什么是多线程?提到多线程这里要说两个概念,就是串行和并行,搞清楚这个,我们才能更好地理解多 ...

  6. FL Studio进行侧链的三种方式(上)

    在本系列教程中,我们将学习如何在FL Studio中进行侧链.侧链是一种信号处理技术,通过它我们可以使用一个信号波形的振幅(音量)来控制另一个信号的某些参数.在电子音乐中,例如trance,house ...

  7. 从维基百科等网站复制公式到MathType中

    在写论文的时候你会想要一些比书本上更好的实例,所以你会在网上寻找资源.当你发现一个你想要的公式时,发现网页公式复制粘贴后太模糊而不适合打印或者投影.这种问题在MathType中如何解决呢? 你可以将网 ...

  8. ABBYY FineReader 15 中保存和导出PDF文档的小细节

    运用ABBYY FineReader OCR文字识别软件,用户能将各种格式的PDF文档保存为新的PDF文档.PDF/A格式文档,以及Microsoft Word.Excel.PPT等格式.在保存与导出 ...

  9. 永别了,Dota2!

    永别了,Dota2 .输了游戏,我还有人生! 游戏中,总有那些喷子,自己玩的不好,经常说人家! 和大便打架,即使赢了,身上也非常臭! 所以对于这种人,敬而远之即可!不吵不闹,默默把锅扛起!赢了,就好说 ...

  10. E - Knapsack 2 题解(超大01背包)

    题目链接 题目大意 给你一n(n<=100)个物品,物品价值最大为1e3,物品体积最多为1e9,背包最大为1e9 题目思路 如果按照平常的背包来算那么时间复杂度直接O(1e11) 这个你观察就发 ...