洛谷4287:双倍回文

前言:

题目描述:

  • 记字符串\(w\)的倒置为\(w^R\)。例如\((abcd)^R=dcba\)。
  • 如果一个字符串能够表示成\(ww^Rww^R\)的形式,责成他是一个双倍回文。
  • 给定一个字符串,求最长双倍回文子串长度。

输入描述:

  • 输入分为两行,第一行输入一个整数表示字符串的长度。
  • 第二行输入只有英文小写的字符串。

输出描述:

  • 输出一个整数表示答案,如果不存在双倍回文子串,则输出0。

思路:

  • 回文自动机模板题:\(trans\)指针的使用。

    • \(trans\)指针:小于等于当前节点长度一半的最长回文后缀,求法和\(fail\)指针类似。
    • 当新建一个节点后,如果他的长度小于等于2,那么这个结点的\(trans\)指针指向他的\(fail\)节点。
    • 否则的话,我们从他的父亲的\(trans\)指针指向的节点开始跳\(fail\)指针。
    • 直到跳到某个结点所表示的回文串的两侧都能拓展这个字符且拓展后的长度小于等于当前节点长度的一半。
    • 那么新建节点的\(trans\)指针就指向该节点的儿子。
  • 考虑一个字符串满足双倍回文:
    • 当且仅当他的\(trans\)指针指向的节点所表示的回文串长度恰好是这个字符串长度的一半,并且这个\(trans\)指针指向的节点所表示的回文串长度为偶数。
    • 枚举每个节点,不停更新答案。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 10; int cnt; //节点个数
int last; //上一个结点
int trie[maxn][30]; //字典树
int len[maxn]; //当前节点的回文串长度
int fail[maxn]; //当前节点的fail指针
int len_str; //字符串的长度
char s[maxn]; //原字符串
int trans[maxn]; //trans指针表示<=当前节点长度一半的最长回文后缀 inline int get_fail(int las, int i)
{
while(s[i - len[las] - 1] != s[i])
las = fail[las];
return las;
} void init()
{
cnt = 1, last = 0;
len[0] = 0, len[1] = -1;
fail[0] = 1, fail[1] = 0;
} void build_PAM()
{
for(int i = 1; i <= len_str; i++)
{
int p = get_fail(last, i);
if(!trie[p][s[i]-'a'])
{
len[++cnt] = len[p] + 2;
fail[cnt] = trie[get_fail(fail[p], i)][s[i]-'a'];
trie[p][s[i]-'a'] = cnt; ///------------顺带求出trans指针
if(len[cnt] <= 2) trans[cnt] = fail[cnt];
///这一题数据较水 博主在这里一开始cnt写的是p
///但是没有被卡掉
///如果他的长度<=2,那么当前节点的trans指向他的fail节点
else
{
int tmp= trans[p];
while((s[i - len[tmp] - 1] != s[i]) || (((len[tmp] + 2)<<1) > len[cnt]))
tmp = fail[tmp];
//开始跳fail指针
//直到跳到某一个节点所表示的回文串两侧都能拓展这个字符
//并且拓展后的长度小于等于当前节点长度的一半.
trans[cnt] = trie[tmp][s[i]-'a'];
}
///------------结束
}
last = trie[p][s[i]-'a'];
}
} int main()
{
scanf("%d", &len_str);
scanf("%s", s + 1); s[0] = '#';
init(); build_PAM();
int ans = 0;
for(int i = 2; i <= cnt; i++) //枚举所有的节点
if((len[trans[i]]<<1)==len[i] && len[trans[i]] % 2 == 0)
ans = max(ans, len[i]);
cout << ans << endl;
return 0;
}

luogu_4287:双倍回文的更多相关文章

  1. 【BZOJ-2342】双倍回文 Manacher + 并查集

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1799  Solved: 671[Submit][Statu ...

  2. BZOJ 2342 双倍回文(manacher算法)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2342 题意:定义双倍回文串为:串的长度为4的倍数且串的前一半.后一半.串本身均是回文的. ...

  3. BZOJ2342: [Shoi2011]双倍回文

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 923  Solved: 317[Submit][Status ...

  4. 【BZOJ2342】双倍回文(回文树)

    [BZOJ2342]双倍回文(回文树) 题面 BZOJ 题解 构建出回文树之后 在\(fail\)树上进行\(dp\) 如果一个点代表的回文串长度为\(4\)的倍数 并且存在长度为它的一半的回文后缀 ...

  5. [SHOI 2011]双倍回文

    Description 题库链接 记一个字符串为 \(X\) ,它的倒置为 \(X^R\) .现在给你一个长度为 \(n\) 的字符串 \(S\) ,询问其最长的形同 \(XX^RXX^R\) 的子串 ...

  6. [SHOI2011]双倍回文

    Description   Input 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. Output 输出文件只有一行,即:输入数据中字符串的最长 ...

  7. BZOJ2342[Shoi2011]双倍回文——回文自动机

    题目描述 输入 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. 输出 输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文 ...

  8. bzoj千题计划306:bzoj2342: [Shoi2011]双倍回文 (回文自动机)

    https://www.lydsy.com/JudgeOnline/problem.php?id=2342 解法一: 对原串构建回文自动机 抽离fail树,从根开始dfs 设len[x]表示节点x表示 ...

  9. 2018.06.30 BZOJ 2342: [Shoi2011]双倍回文(manacher)

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec Memory Limit: 128 MB Description Input 输入分为两行,第一行为一个整数,表示字符串 ...

随机推荐

  1. Field "details" doesn't have a default value

    [转载:原文链接http://my.oschina.net/wojibuzhu/blog/511104] MySQL 1364 错误提示:#1364 - Field "details&quo ...

  2. 用shell脚本批量进行xss跨站攻击请求

    由于执行的xss攻击请求他多了,初步估计要执行83次,而且还要执行3篇,如果手工一个一个去执行,说出去,我还配叫自动化大师吗: 有鉴于此,边打算自己编写一个脚本进行批量执行: 而短脚本的编写,非she ...

  3. 关于 Windows to go

    1. 在宿主计算器的操作系统中访问 Windows to go 的磁盘 如题,如果需要在宿主计算器的操作系统中访问 Windows to go 的U盘(移动硬盘)中的文件,只需要打开磁盘管理,“更改驱 ...

  4. Replication:The replication agent has not logged a progress message in 10 minutes.

    打开Replication Monitor,在Subscription Watch List Tab中,发现有大量的status= “Performance critical” 的黄色Warning, ...

  5. MQTT --- 操作行为

    会话状态 为实现QoS等级1和QoS等级2协议流,客户端和服务端需要将状态与客户标识符相关联,这被称为会 话状态.服务端还将订阅信息存储为会话状态的一部分.会话可以跨越一系列的网络连接.它持续到最新的 ...

  6. Linux中Crontab的使用

    一.安装依赖 yum install cronie 二.添加 Crontab crontab -e 三.查看crontab内容 crontab -l 其中常见的一些内容 例子: # 每月的最后1天 0 ...

  7. JDBC 复习

    概念 Java DataBase Connectivity java数据库连接 定义了操作所有关系型数据库的规则(接口),不同的数据库厂商编写类实现这些接口,这些类就叫数据库驱动,使得用户只需要使用统 ...

  8. 【转载】C#中SqlCommand类的作用以及常用方法

    在C#的数据库操作过程中,SqlCommand类一般用于Sqlserver数据库的SQL语句的执行,包括Select语句.Update语句.Delete语句以及SQL存储过程等,SqlCommand的 ...

  9. 如何将一个div盒子水平垂直都居中?

    html代码如下: 固定样式: 方法一:利用定位(常用方法,推荐) .parent{ position:relative; } .child{ position:absolute; top:50%; ...

  10. Nginx学习(一)

    Nginx I/O模型 网络I/O 本质是socket读取 第一步:将数据从磁盘文件先加载至内核内存空间(暖冲区),等待数据准备完成,时间较长. 第二部:将数据从内核缓冲区复制到用户空间的进程的内存中 ...