CF 827E Rusty String FFT
如果没有碍事的?
的话,判定字符串的循环节直接用KMP的失配数组就可以搞定。现在有了碍事的?
,我们就需要考虑更通用的算法。
考虑KMP失配数组判定字符串循环节的本质,发现判定\(k\)是否为字符串的循环节等价于判定字符串在右移\(k\)位后能否和原字符串匹配(只考虑二者重叠的部分)。
我们不妨先把?
直接看成一个可以匹配任何字符的通配符,而解决带通配符的字符串匹配问题的一个算法就是FFT。
(以下默认下标为\(0\)~\(n-1\))
设字符串为\(s\),因为字符集只有\(2\),不妨直接枚举不能匹配的两种情况。定义\(a_i=[s_i='V']\),\(b_i=[s_i='K']\),另一种情况只需要把定义反过来就行了。
再定义一个数组
\]
(另一种情况式子是一样的)
发现\(s\)右移\(i\)位后能和原串匹配当且仅当两种情况的\(c_i\)都为\(0\)。
而上面的式子把\(\{a_i\}\)反转后就是
\]
跑两遍卷积即可。
然而还是会发现一些问题……从样例就能看出来,这里的?
其实并不是通配符,因为在判定循环节时一个?
在不同的位置必须代表相同的字符(可能有点抽象,参见第一组样例中2为什么可以匹配但不是循环节)。
然而这个问题其实并不棘手。我们都知道如果一个数真的是循环节那么它的所有倍数也一定是循环节,所以对于那些\(c_i\)为\(00\)的位置再判断一下它的倍数是否也都满足\(c_i=0\)就行了。
(完整证明参见官方题解)
这一步的复杂度是\(O(n\log n)\)的,不会影响到总复杂度。
另外,考虑到问题的特殊性,其实不必跑两遍卷积,任意跑其中一种情况即可,两种情况的\(c_i\)分别是\(\left(a^R*b\right)_{n-i-1}\)和\(+\left(a^R*b\right)_{n+i-1}\)(可以从两种情况的对称性的角度理解)。
(我比较懒写的是NTT)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1048600,p=998244353,g=3;
void NTT(int*,int,int);
int qpow(int,int);
char s[maxn];
bool ans[maxn];
int T,n,A[maxn],B[maxn];
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%s",&n,s);
int N=1;
while(N<(n<<1))N<<=1;
memset(A,0,sizeof(int)*N);
memset(B,0,sizeof(int)*N);
for(int i=0;i<n;i++){
if(s[i]=='V')A[n-i-1]=1;
else if(s[i]=='K')B[i]=1;
}
NTT(A,N,1);
NTT(B,N,1);
for(int i=0;i<N;i++)A[i]=(long long)A[i]*B[i]%p;
NTT(A,N,-1);
int cnt=0;
for(int i=1;i<=n;i++){
ans[i]=true;
for(int j=i;j<=n;j+=i)ans[i]&=!(A[n-j-1]+A[n+j-1]);
cnt+=ans[i];
}
printf("%d\n",cnt);
for(int i=1;i<=n;i++)
if(ans[i]){
printf("%d",i);
if(--cnt)printf(" ");
}
printf("\n");
}
return 0;
}
void NTT(int *A,int n,int tp){
for(int i=1,j=0,k;i<n-1;i++){
k=n;
do j^=(k>>=1);while(j<k);
if(i<j)swap(A[i],A[j]);
}
for(int k=2;k<=n;k<<=1){
int wn=qpow(g,tp>0?(p-1)/k:p-1-(p-1)/k);
for(int i=0;i<n;i+=k){
int w=1;
for(int j=0;j<(k>>1);j++,w=(long long)w*wn%p){
int a=A[i+j],b=(long long)w*A[i+j+(k>>1)]%p;
A[i+j]=a+b;
if(A[i+j]>=p)A[i+j]-=p;
A[i+j+(k>>1)]=a-b;
if(A[i+j+(k>>1)]<0)A[i+j+(k>>1)]+=p;
}
}
}
if(tp<0){
int inv=qpow(n,p-2);
for(int i=0;i<n;i++)A[i]=(long long)A[i]*inv%p;
}
}
int qpow(int a,int b){
int ans=1;
for(;b;b>>=1,a=(long long)a*a%p)if(b&1)ans=(long long)ans*a%p;
return ans;
}
CF 827E Rusty String FFT的更多相关文章
- Codeforces 827E Rusty String - 快速傅里叶变换 - 暴力
Grigory loves strings. Recently he found a metal strip on a loft. The strip had length n and consist ...
- 【CF827E】Rusty String 调和级数+FFT
[CF827E]Rusty String 题意:给你一个01串,其中部分字符是'?',?可以是0或1,求所有可能的d,满足存在一种可能得到的01串,在向右移动d格后与自己相同. $n\le 5\tim ...
- E. Rusty String
E. Rusty String time limit per test 3 seconds memory limit per test 512 megabytes input standard inp ...
- 【题解】Rusty String [CF827E]
[题解]Rusty String [CF827E] 传送门:\(\text{Rusty String}\) \(\text{[CF827E]}\) [题目描述] 多组数据,每组数据给出一个由 \(V, ...
- CF 1131 E. String Multiplication
E. String Multiplication 题意 分析: 从后往前考虑字符串变成什么样子. 设$S_i = p_1 \cdot p_2 \dots p_{i}$,最后一定是$S_{n - 1} ...
- CF 1003B Binary String Constructing 【构造/找规律/分类讨论】
You are given three integers a, b and x. Your task is to construct a binary string s of length n=a+b ...
- CF #541 E. String Multiplication
题意: 给定一系列字符串,每次都是后一个字符串和前面的融合,这个融合操作就是原来的串分成独立的,然后把新串插入到这些空格中.问最后,最长的相同连续的长度. 思路: 这道题可以贪心的来,我们压缩状态,记 ...
- CF 1140B Good String
Description You have a string ss of length nn consisting of only characters > and <. You may d ...
- 【CF 710F】String Set Queries
在校内OJ上A了,没有加强制在线的东西..不放链接了. 这道题题意是维护一个字符串集合,支持三种操作: 1.加字符串 2.删字符串 3.查询集合中的所有字符串在给出的模板串中出现的次数 操作数\(m ...
随机推荐
- jmeter插件之自定义场景图(万能场景设计)
添加扩展插件 自定义线程组:jp@gc - Ultimate Thread Group 此线程组功能强大,可以实现多种场景设置,添加路径如图 参数含义解释 Start Threads Count:当前 ...
- css实现栏目两边斜线的效果
实现效果: 具体实现代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...
- C#4.0使用dynamic 动态添加属性
最近做一个项目,用wpf mvvm实现,而前台表格需要根据数据库某表的设置不同生成不同的列名.过去用winform和Ado.net实现这种功能的时候就只需要拼装DataTable,拼成最后需要的表格, ...
- web应用配置虚拟路径映射方式一配置不成功问题解决办法
配置过程图: 为了方便输入,先修改Tomcat的conf文件下的server.xml文件 默认端口修改为80 配置完成之后访问报404错误解决办法: 一.如果配置前已经开启了Tomcat服务器,配置完 ...
- L09-Linux系统修改网卡名称(eth1修改为eth0)
一.环境 VirtualBox + CentOS6.5 二.问题 有时候在克隆服务器之后配置网络时,或者在维护别人建好的服务器时,会遇到这样一种情况.如下图所示: 即:在接口配置文件ifcfg-e ...
- (转)MySQL字段类型详解
MySQL字段类型详解 原文:http://www.cnblogs.com/100thMountain/p/4692842.html MySQL支持大量的列类型,它可以被分为3类:数字类型.日期和时间 ...
- Linq基础知识小记一
1.LINQ(语言级集成查询)的作用就是提供一种统一且对称的方式,让程序员在广义的数据上获取和操作数据.广义的数据包括XML文档数据.元数据.System.Data.dll和System.Data.S ...
- 开发小技巧1——Logger
开发小技巧1——Logger 在项目中加入静态Logger类,用于捕获并记录程序的进度.错误信息: public static class Logger { public static void ...
- Eclipse安装fat jar的两种方式
help >software updates >add/remove software>add>>add site填写name 和urlname:Fat Jarurl:h ...
- oracle 执行的时候,显式输出结果!: set serveroutput on;