Problem Description One day, sailormoon girls are so delighted that

they intend to research about palindromic strings. Operation contains

two steps: First step: girls will write a long string (only contains

lower case) on the paper. For example, “abcde”, but ‘a’ inside is not

the real ‘a’, that means if we define the ‘b’ is the real ‘a’, then we

can infer that ‘c’ is the real ‘b’, ‘d’ is the real ‘c’ ……, ‘a’ is the

real ‘z’. According to this, string “abcde” changes to “bcdef”. Second

step: girls will find out the longest palindromic string in the given

string, the length of palindromic string must be equal or more than 2.

Input Input contains multiple cases. Each case contains two parts, a

character and a string, they are separated by one space, the character

representing the real ‘a’ is and the length of the string will not

exceed 200000.All input must be lowercase. If the length of string is

len, it is marked from 0 to len-1.

Output Please execute the operation following the two steps. If you

find one, output the start position and end position of palindromic

string in a line, next line output the real palindromic string, or

output “No solution!”. If there are several answers available, please

choose the string which first appears.

Sample Input

b babd
a abcd

Sample Output

0 2
aza
No solution!

思路如下

这题暴力准超时,但是还有有一种神奇的算法 Manachar 经过预处理后可以以O(n)来解决这个题

马拉车算法传送门

辅助理解转送门

Manachar代码注释

#include<iostream>
#include<string.h>
using namespace std; const int Max = 1e5;
char ar[Max]; //原始字符串
char br[Max << 2]; //存储转化后的字串
int Len[Max << 2]; //Len[i] 计算为以br[i]字符为中心的回文子串的长度,还有要注意一个规律:Len[i] - 1 为以br[i]为中心的回文子串的组成字符个数 //转换字符串
int trans_ar(char ar[])
{
int Len_ar = (int)strlen(ar);
br[0] = '@';
for(int i = 1; i <= 2 * Len_ar; i +=2)
{
br[i] = '#';
br[i + 1] = ar[i / 2];
}
br[2 * Len_ar + 1] = '#';
br[2 * Len_ar + 2] = '\0';
return 2 * Len_ar + 1;
}
//Manachar 算法过程
int Manachar(char br[],int Len_br)
{
int R = 0,mid = 0,ans = 0; //R 为当前正计算的回文中心i之前的所有回文子串,所能延伸至的最右端 的下一个数
//mid 为右端延伸至R处的回文子串的中心
for(int i = 1; i <= Len_br; i ++)
{
if(i < R)
Len[i] = min(R - i , Len[2 * mid - i]); //2 * mid - i = j ( i 与 j 关于 mid对称,根据回味子串的对称性质,我们直接让 Len[i] = Len[j] 加速查找,但是Len[j] 要小于 R - mid)
//举例证明 : c # a # c # a # b #
// 1 2 3 4 5 6 7 8 9 10
else
Len[i] = 1; //无法根据回文的性质进行加速了,只能老老实实的向两边延伸了 while(br[i - Len[i]] == br[i + Len[i]]) //向两边延伸进行判断回文半径长度
Len[i] ++; if(Len[i] + i > R) //Len[i] + i 当前以 i 为中心的回文子串所能延伸的最右端的距离
{
R = Len[i] + i;
mid = i;
}
ans = max(ans , Len[i]); //ans存储最大长度
}
return ans - 1;
} int main()
{
//freopen("test_3.txt","r",stdin);
int n;
cin>>n;
for(int i = 0; i < n; i++)
cin>>ar[i]; //转化字符串ar为br,并获取转换问之后br的长度
int Len_br = trans_ar(ar);
//求最大回文子串的长度
int ans = Manachar(br,Len_br);
cout<<ans<<endl; return 0;
}

题解如下

//hdu 3294
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std; const int Len = 200005;
char ar[Len],br[Len << 2];
int Ridus[Len << 2];
char ch; void change(char ar[])
{
int Len_ar = (int)strlen(ar);
int cha = ch - 'a';
for(int i = 0; i < Len_ar; i++)
{
ar[i] -= cha;
if (ar[i] < 'a')
ar[i] += 26;
}
} int trans_ar(char ar[])
{
int Ridus_ar = (int)strlen(ar);
br[0] = '@';
for(int i = 1; i <= 2 * Ridus_ar; i +=2)
{
br[i] = '#';
br[i + 1] = ar[i / 2];
}
br[2 * Ridus_ar + 1] = '#';
br[2 * Ridus_ar + 2] = '\0';
return 2 * Ridus_ar + 1;
} //Manachar 算法过程
int Manachar(char br[],int Ridus_br)
{
int R = 0,mid = 0,ans = 0; //R 为当前正计算的回文中心i之前的所有回文子串,所能延伸至的最右端 的下一个数
//mid 为右端延伸至R处的回文子串的中心
for(int i = 1; i <= Ridus_br; i ++)
{
if(i < R)
Ridus[i] = min(R - i , Ridus[2 * mid - i]); //2 * mid - i = j ( i 与 j 关于 mid对称,根据回味子串的对称性质,我们直接让 Ridus[i] = Ridus[j] 加速查找,但是Ridus[j] 要小于 R - mid)
else
Ridus[i] = 1; //无法根据回文的性质进行加速了,只能老老实实的向两边延伸了 while(br[i - Ridus[i]] == br[i + Ridus[i]]) //向两边延伸进行判断回文半径长度
Ridus[i] ++;
if(Ridus[i] + i > R) //Ridus[i] + i 当前以 i 为中心的回文子串所能延伸的最右端的距离
{
R = Ridus[i] + i;
mid = i;
}
ans = max(ans , Ridus[i]); //ans存储最大长度
}
return ans - 1;
} int main()
{
// freopen("test_3.txt","r",stdin);
while(cin>>ch>>ar)
{
change(ar);
int Len_br = trans_ar(ar);
int ans = Manachar(br,Len_br);
if(ans >= 2)
{
for(int i = 1;i <= Len_br; i ++)
{
if(Ridus[i] == ans + 1)
{
int st = (i - ans) / 2; //st * 2 + 2 = mid - r + 1
int ed = (i + ans - 2) / 2; //ed * 2 + 2 = mid + r - 1
cout<<st<<" "<<ed<<endl;
for(int j = i - ans; j <= i + ans; j ++)
if(br[j]>= 'a' && br[j] <= 'z')
cout<<br[j];
cout<<endl;
break;
}
}
}
else
cout<<"No solution!\n";
}
return 0;
}

Girls' research(马拉车算法) hdu 3294的更多相关文章

  1. HDU3294 Girls' research —— Manacher算法 输出解

    题目链接:https://vjudge.net/problem/HDU-3294 Girls' research Time Limit: 3000/1000 MS (Java/Others)    M ...

  2. Hdu 3294 Girls' research (manacher 最长回文串)

    题目链接: Hdu 3294  Girls' research 题目描述: 给出一串字符串代表暗码,暗码字符是通过明码循环移位得到的,比如给定b,就有b == a,c == b,d == c,.... ...

  3. (回文串 Manacher )Girls' research -- hdu -- 3294

    http://acm.hdu.edu.cn/showproblem.php?pid=3294 Girls' research Time Limit:1000MS     Memory Limit:32 ...

  4. HDU 3294 Girls' research(manachar模板题)

    Girls' researchTime Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total ...

  5. Manacher 算法(hdu 3068 && hdu 3294)

    今天打算补前晚 BC 的第二题,发现要用到能在 O(n) 时间求最大回文子串长度的 Manacher 算法,第一次听,于是便去百度了下,看了大半天,总算能看懂了其思想,至于他给出的代码模板我没能完全看 ...

  6. HDU - 3068 最长回文manacher马拉车算法

    # a # b # b # a # 当我们遇到回判断最长回文字符串问题的时候,若果用暴力的方法来做,就是在字符串中间添加 #,然后遍历每一个字符,找到最长的回文字符串.那么马拉车算法就是在这个基础上进 ...

  7. 回文串--- Girls' research

    HDU   3294 Problem Description One day, sailormoon girls are so delighted that they intend to resear ...

  8. Best Reward && Girls' research

    After an uphill battle, General Li won a great victory. Now the head of state decide to reward him w ...

  9. HDU----(3294)Girls' research(manacher)

    Girls' research Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)T ...

随机推荐

  1. Vue父子组件通讯

    我们知道,父组件不能修改子组件的数据[这种说法是不严谨的],严谨的说法是:子组件内部不能修改从父组件传递过来的值.原因是vue遵循的是数据单向流原则,父组件传递数据给子组件只能单向绑定,通过Props ...

  2. activiti设置customSessionFactories时的一个小坑

    现象:activiti设置customSessionFactories不起作用,流程还是走原来的查询方法原因:新实现的XXXEntityManagerFactory的getSessionType方法返 ...

  3. C++ 回调函数,拷贝文件

    #include <iostream> #include <windows.h> using namespace std; unsigned long long transla ...

  4. 2020年IOS超级签最新实现原理详解

    相信2019年最火的应该就是这个东西了,我也是摸着石头过河,勉强混进了这个行业! 超级签这个东西吧,说白了就是用个人账号分发应用,大致分成以下几个步骤吧 一.使用配置文件获取UDID 苹果公司允许开发 ...

  5. nodejs中的并发编程

    从sleep的实现说起 在nodejs中,如果要实现sleep的功能主要是通过"setTimeout + promise"实现,也可以通过"循环空转"来解决.前 ...

  6. 可运行jar包的几种打包/部署方式(转)

    转自:https://www.cnblogs.com/yjmyzz/p/executable-jar.html java项目开发中,最终生成的jar,大概可分为二类,一类是一些通用的工具类(不包含ma ...

  7. 我的Keras使用总结(2)——构建图像分类模型(针对小数据集)

    Keras基本的使用都已经清楚了,那么这篇主要学习如何使用Keras进行训练模型,训练训练,主要就是“练”,所以多做几个案例就知道怎么做了. 在本文中,我们将提供一些面向小数据集(几百张到几千张图片) ...

  8. 工作中常用到的Java集合类有哪些?

    前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y Java集合是我认为在Java基础中最最重要的知 ...

  9. List集合概述和特点

    List集合概述 有序集合(也称序列)用户可以精确控制列表的每一个元素的位置插入,用户可以通过整数索引访问元素,并搜索列表中的元素 与set集合不同,列表通常允许重复的元素 List集合的特点 有序: ...

  10. 李瑞红 201771010111《面向对象程序设计(java)》第一周学习总结

    李瑞红 201771010111<面向对象程序设计(java)>第一周学习总结 第一部分:课程准备部分 填写课程学习 平台注册账号, 平台名称 注册账号 博客园:www.cnblogs.c ...