HDU - 3068
Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理) 字符串长度len <= 110000 Output 每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
Sample Input aaaa abab Sample Output 4 3 Source |
题目要求求出最长回文子串,是一道manacher的模板题。
我们先讲一下manacher,我们先处理一下字符串,把字符串处理成#a#a#这样的格式,比如abcd处理成#a#b#c#d#,这样的好处是解决了判断回文串是奇数和偶数的问题,把回文串强制变成奇数。接下来,定义一个p[]数组,p[i]代表以节点i为中心的最长回文串的半径。例如aaaa这个字符串,p[0]=p[3]=1,p[1]=p[2]=2。同时我们定义一个变量mx和id,mx代表当前判断过的回文子串最长延伸(往右)到哪里,可以理解为当前判断过的回文子串到达的最大下标。而id代表当前更新的mx值所对应的回文串的中心的下标。如果不是很清楚可以直接看下代码。剩下部分直接看代码注释吧。最好自己在纸上画一下
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #define X first #define Y second #define clr(u,v); memset(u,v,sizeof(u)); using namespace std; typedef long long ll; typedef pair<int,int> pii; const int maxn=2e5+10;//注意开两倍大小 const int INF=0x3f3f3f3f; char s[maxn],str[maxn];//s为原字符串,str为处理后的字符串 int p[maxn];//p[i]代表以i为中心的回文串的最长半径 int len1,len2;//分别代表s的长度和str的长度 void init()//预处理出str { len1=strlen(s); str[0]='$';//在首位加一个特殊字符,防止越界 str[1]='#'; for (int i=0;i<len1;i++) { str[2*i+2]=s[i]; str[2*i+3]='#'; } len2=len1*2+2; str[len2]='