题意

给定一个字符串 \(S\)

求所有的 \(S[i,n-i+1]\) 的 \(border\) 长度(最长的前缀等于后缀),要求长度是奇数

\(n\le 10^6\)

Sol

首先发现每次求的串都是原串去掉前后 \(i-1\) 位得到的串

一个套路,把串翻折,又因为 \(border\) 长度可能大于一半,所以我们把串倍长后翻折

也就是翻转过来隔空插入在一起

例如:

串 \(bcabcabcabcabca\)

翻转后 \(acbacbacbacbacb\)

隔一个插入在一起 \(baccabbaccabbaccabbaccabbaccab\)

那么也就是求这个串的以某个位置的开始的最长回文串

又因为得到的这个串本身就是回文串,所以并不用翻转过来,直接求以某个位置的结束的最长回文串就好了

比如 \(baccab\) 就是 \(S[1,3]\) 和 \(S[13,15]\)

回文树就好了

注意到每次都要跳 \(fail\) 链跳到满足要求的位置,而每次都跳很耗时

如果之后跳到之前跳到过的点,就可以直接跳到之前跳到的对答案有贡献的点上

再继续跳

并查集维护一下就好了

# include <bits/stdc++.h>
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll; IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
} const int maxn(2e6 + 5); int n, last, tot, anc[maxn], id[maxn];
int len[maxn], first[maxn], nxt[maxn], type[maxn], fa[maxn];
char s[maxn], str[maxn]; IL int Son(RG int u, RG int c){
for(RG int v = first[u]; v; v = nxt[v])
if(type[v] == c) return v;
return 0;
} IL void Link(RG int u, RG int v, RG int c){
nxt[v] = first[u], first[u] = v, type[v] = c;
} IL void Extend(RG int pos, RG int c){
RG int p = last;
while(s[pos - len[p] - 1] != s[pos]) p = fa[p];
if(!Son(p, c)){
RG int np = ++tot, q = fa[p];
while(s[pos - len[q] - 1] != s[pos]) q = fa[q];
len[np] = len[p] + 2, fa[np] = Son(q, c);
Link(p, np, c);
}
last = Son(p, c);
} IL int Find(RG int x){
return anc[x] == x ? x : anc[x] = Find(anc[x]);
} int main(){
Fill(type, -1), n = Input(), scanf(" %s", str + 1);
for(RG int t = 0, i = 1, j = n; j; ++i, --j)
s[++t] = str[i], s[++t] = str[j];
tot = 1, fa[0] = fa[1] = 1, len[1] = -1, n <<= 1, anc[0] = 1;
for(RG int i = 1; i <= n; ++i) Extend(i, s[i] - 'a'), id[i] = last;
for(RG int i = 0; i <= tot; ++i) anc[i] = i;
for(RG int i = 1, m = n >> 1, t = (m + 1) >> 1; i <= t; ++i){
RG int x = Find(id[n - ((i - 1) << 1)]);
while(x != 1 && ((len[x] >> 1) >= (m - ((i - 1) << 1)) || len[x] % 4 != 2)) x = anc[x] = Find(fa[anc[x]]);
printf("%d ", (len[x] % 4 == 2) ? (len[x] >> 1) : -1);
}
return 0;
}

CF961F k-substrings的更多相关文章

  1. 【HDU 5030】Rabbit's String (二分+后缀数组)

    Rabbit's String Problem Description Long long ago, there lived a lot of rabbits in the forest. One d ...

  2. hdu 5030 Rabbit&#39;s String(后缀数组&amp;二分法)

    Rabbit's String Time Limit: 40000/20000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  3. django模型操作

    Django-Model操作数据库(增删改查.连表结构) 一.数据库操作 1.创建model表        

  4. 【POJ 3415】Common Substrings 长度不小于k的公共子串的个数

    长度不小于k的公共子串的个数,论文里有题解,卡了一上午,因为sum没开long long!!! 没开long long毁一生again--- 以后应该早看POJ里的Discuss啊QAQ #inclu ...

  5. POJ-Common Substrings(后缀数组-长度不小于 k 的公共子串的个数)

    题意: 长度不小于 k 的公共子串的个数 分析: 基本思路是计算 A 的所有后缀和 B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于 k 的部分全部加起来. 先将两个字符串连起来,中间 ...

  6. POJ 3415 Common Substrings(长度不小于K的公共子串的个数+后缀数组+height数组分组思想+单调栈)

    http://poj.org/problem?id=3415 题意:求长度不小于K的公共子串的个数. 思路:好题!!!拉丁字母让我Wa了好久!!单调栈又让我理解了好久!!太弱啊!! 最简单的就是暴力枚 ...

  7. POJ 3415 Common Substrings 【长度不小于 K 的公共子串的个数】

    传送门:http://poj.org/problem?id=3415 题意:给定两个串,求长度不小于 k 的公共子串的个数 解题思路: 常用技巧,通过在中间添加特殊标记符连接两个串,把两个串的问题转换 ...

  8. Common Substrings POJ - 3415(长度不小于k的公共子串的个数)

    题意: 给定两个字符串A 和 B, 求长度不小于 k 的公共子串的个数(可以相同) 分两部分求和sa[i-1] > len1  sa[i] < len1  和  sa[i-1] < ...

  9. POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)

    Description A substring of a string T is defined as: T( i, k)= TiTi+1... Ti+k-1, 1≤ i≤ i+k-1≤| T|. G ...

  10. CSU-1632 Repeated Substrings (后缀数组)

    Description String analysis often arises in applications from biology and chemistry, such as the stu ...

随机推荐

  1. AWS 推出长期支持的 OpenJDK 免费分发版本 —— Amazon Corretto

    简评:听说 Oracle JDK 要收费了,Oracle 要限制 Java 的商业或生产用途,针对这个问题,AWS 将会推出 Amazon Corretto. Java 是 AWS 用户使用的最流行的 ...

  2. 利用python 学习数据分析 (学习二)

    内容学习自: Python for Data Analysis, 2nd Edition         就是这本 纯英文学的很累,对不对取决于百度翻译了 前情提要: 各种方法贴: https://w ...

  3. web站点启用https (一)

    HTTPS技术是现在主流网站都采用的安全加密传输数据的技术,本篇文档将分为2部分讲解PKI的基本原理及在web站点配置https访问. 一.理论知识 1.PKI(public key infrastr ...

  4. SDN定义网络

    http://edu.51cto.com/course/course_id-4466.html http://edu.51cto.com/course/course_id-4497.html

  5. Eclipse安装genymotion最新的方法

    https://www.cnblogs.com/WXBai/p/5938884.html 安卓开发: http://tools.android-studio.org/index.php/sdkhttp ...

  6. [原创]SSH 隧道转发

    目录 简介 本地SSH隧道 远程SSH隧道 FAQ 免密码登陆 自动重连 简介 建立ssh隧道常用于, 通过一台公网的主机或者是大家都可以访问的主机做跳转机,来访问内部或者外部不能直接访问的机器. 项 ...

  7. python 全栈开发:数据类型整体分析

    数据类型初始 数据类型:    int :用于计算. 例子:1.2.3.4........................... 常用方法操作: bit_length()   ps:求一个数字转换成二 ...

  8. 算法图解学习笔记01:二分查找&大O表示法

    二分查找 二分查找又称折半查找,其输入的必须是有序的元素列表.二分查找的基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止:如果x<a[ ...

  9. (转)OpenStack各服务所用端口号总结

    参考:Firewalls and default ports 注:可执行 sudo netstat -tnlp 查看 端口 服务描述 22 SSH 3306 MariaDB(MySQL) 27017 ...

  10. kafka多线程消费topic的问题

    案例: topic:my-topic,分区:6 消费者:部署三台机器,每台机器上面开启6个线程消费. 消费结果:只有一台机器可以正常消费,另外两台机器直接输出六条告警日志: No broker par ...