BZOJ 2565 最长双回文串
2017-11-24 17:24
190 查看
Descri
4000
ption
顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
Input
一行由小写英文字母组成的字符串S。
Output
一行一个整数,表示最长双回文子串的长度。
Sample Input
baacaabbacabb
Sample Output
12
HINT
样例说明
从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。
对于100%的数据,2≤|S|≤105。
2015.4.25新加数据一组
Source
2012国家集训队Round 1 day2
思路
首先maracher跑一遍,然后分别更新一个点i不包含它的左侧的最长回文子串和右侧的最长回文字串的长度(记为li和ri),就拿这个串来说吧:abbab,扩充后得到#b#a#b#b#a#b#这个串,那么第6个(倒数第2个)#号左侧的最长回文字串就是abba,右侧的最长回文字串就是b,注意是原串的长度。
那么计算li时,由于选择串需要尽量选择最长的,就是串的中心越小越好,因此可以从左到右扫一遍,把还没有计算的都计算了,下次计算时又从还没有计算的第一个位置开始计算,这样能够确保时间复杂度为O(n),计算右侧时同理。
还有些细节在代码中讲。
代码
4000
ption
顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
Input
一行由小写英文字母组成的字符串S。
Output
一行一个整数,表示最长双回文子串的长度。
Sample Input
baacaabbacabb
Sample Output
12
HINT
样例说明
从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。
对于100%的数据,2≤|S|≤105。
2015.4.25新加数据一组
Source
2012国家集训队Round 1 day2
思路
首先maracher跑一遍,然后分别更新一个点i不包含它的左侧的最长回文子串和右侧的最长回文字串的长度(记为li和ri),就拿这个串来说吧:abbab,扩充后得到#b#a#b#b#a#b#这个串,那么第6个(倒数第2个)#号左侧的最长回文字串就是abba,右侧的最长回文字串就是b,注意是原串的长度。
那么计算li时,由于选择串需要尽量选择最长的,就是串的中心越小越好,因此可以从左到右扫一遍,把还没有计算的都计算了,下次计算时又从还没有计算的第一个位置开始计算,这样能够确保时间复杂度为O(n),计算右侧时同理。
还有些细节在代码中讲。
代码
#include <cstdio> #include <cstring> const int maxn=100000; char s[maxn+10],a[(maxn<<1)+10]; int p[(maxn<<1)+10],l[(maxn<<1)+10],r[(maxn<<1)+10],id,rmax,len,ans; int main() { scanf("%s",s+1); len=strlen(s+1); a[0]='!'; a[1]='$'; for(register int i=1; i<=len; ++i) { a[i<<1]=s[i]; a[i<<1|1]='$'; } len=len<<1|1; a[len+1]='*';//预处理 p[1]=id=rmax=1; for(register int i=2; i<=len; ++i)//maracher { if(i>rmax) { p[i]=1; } else { if(rmax-i>p[(id<<1)-i]) { p[i]=p[(id<<1)-i]; } else { p[i]=rmax-i; } } while(a[i+p[i]]==a[i-p[i]]) { ++p[i]; } if(i+p[i]-1>rmax) { rmax=i+p[i]-1; id=i; } } int now=0;//now记录最后一个更新的是哪一个位置 for(register int i=1; i<=len; ++i) { for(register int j=now+1; j<=i+p[i]; ++j) { l[j]=j-i;//从上一个没有更新的位置开始,一直计算到不能用i位置更新为止 } if(i+p[i]+1>now) { now=i+p[i];//更新now值 } } //上一次扫描完成后,now一定为n for(register int i=len; i>=1; --i) { for(register int j=now-1; j>=i-p[i]; --j) { r[j]=i-j;//这个i-j和上面的j-i可以推出来,因为不考虑预处理时插入的字符'$' } if(i-p[i]-1<now) { now=i-p[i]; } } for(register int i=1; i<=len; i+=2)//只计算预处理时插入的字符 { if(l[i]+r[i]>ans) { ans=l[i]+r[i]; } } printf("%d\n",ans); return 0; }
相关文章推荐
- 【bzoj 2565】最长双回文串(manacher)
- bzoj 2565: 最长双回文串 manachar
- bzoj2565 最长双回文串
- bzoj 2565 最长双回文串 manacher
- bzoj 2565: 最长双回文串 manacher
- BZOJ 2565: 最长双回文串 [Manacher]
- bzoj 2565: 最长双回文串
- BZOJ 2565 最长双回文串 Hash+二分
- BZOJ 2565 最长双回文串
- BZOJ2565 最长双回文串(回文树)
- [BZOJ]2565 最长双回文串 Manacher+单调队列
- [BZOJ2565]最长双回文串(manacher)
- [BZOJ2565]最长双回文串(manacher)
- BZOJ 2565 最长双回文串 Manacher
- bzoj 2565 最长双回文串 - Manacher
- BZOJ_2565_最长双回文串_manacher
- BZOJ 2565 最长双回文串 Manacher
- BZOJ 2565: 最长双回文串
- BZOJ 2565 最长双回文串(回文自动机)
- bzoj 2565: 最长双回文串