[最长回文子序列Manacher]4.11终于出线了啊!
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[最长回文子序列Manacher]4.11终于出线了啊!相关的知识,希望对你有一定的参考价值。
Manacher用来求最长回文子序列
1.读入字符串,在每个字符前后加一个没有在原字符串中出现的字符,这样不论是奇数或者偶数个都变成了奇数个
例如:
M A N A C H E R
# M # A # N # A # C # H # E # R #
2.在开头和末尾再添加一个没有在原字符串中出现的字符,这样就不用讨论越界了
例如:
# M # A # N # A # C # H # E # R #
$# M # A # N # A # C # H # E # R # \0
3.然后从第一位开始计算到i时,前面有多少位和后面匹配上了(扩展长度),存在cnt数组(匹配半径)里
—————————————————————手动分割线—————————————————————————
/*贴一下代码,例题是hihocoder1032*/
#include <bits/stdc++.h>
using namespace std;
const int L=2000005;
//因为要添加字符,所以长度开字符串的两倍
int N,cnt[L],l1,l2;
char s1[L],s2[L];
int main()
{
scanf ("%d",&N);
while(N--)
{
scanf ("%s",&s1);
l1=strlen(s1);
l2=0;
s2[l2++]=‘$‘;
s2[l2++]=‘#‘;
for (int i=0;i<l1;i++)
{
s2[l2++]=s1[i];
s2[l2++]=‘#‘;
}
s2[l2]=‘\0‘;
memset(cnt,0,sizeof(cnt));
for (int i=1,j=0;i<l2;i++)//j表示当前已知的最大回文串的中点
{
if (cnt[j]+j>i) cnt[i]=min(cnt[2*j-i],cnt[j]-(i-j));
//cnt[j]+j是目前最靠末尾的边界,如果没有越界,已匹配长度就是[和他关于j点对称点的长度或者是最大长度减去他们之间的长度]的较小值
else cnt[i]=1;//越界从1开始计数
for (cnt[i];s2[i-cnt[i]]==s2[i+cnt[i]];cnt[i]++);//挨个匹配
if(i+cnt[i]>j+cnt[j]) j=i;//如果新边界范围更广就替换掉
}
int ans=0;
for (int i=0;i<l2;i++)
if (cnt[i]>ans) ans=cnt[i];//找到最大值
printf ("%d\n",ans-1);
}
return 0;
}
—————————————————————手动分割线—————————————————————————
关于min(cnt[2*j-i],cnt[j]-(i-j))
cnt[2*j-i]是匹配完的部分也没有越界,cnt[j]-(i-j)是匹配部分超过边界,所以只能匹配边界以内的部分
我刚才尝试画了个图发现太麻烦了索性算了,就自己意会一下好了
—————————————————————讲解部分结束的分割线—————————————————————————
这真是一篇很正式的讲解啊
甚至都没用冰晶蝶灵· Q·紫梦雪雅殇雪的七彩琉璃泪
这么正经我都不习惯了啊
(还是冰晶蝶灵· Q·紫梦雪雅殇雪的七彩琉璃泪更好看一点啊)
今天很开心,5班的男生们终于进八强了
从去年的一次又一次的被罚球绝杀
到今天比分一直咬得很紧直到最后马鸡羊的扣篮反杀真是帅爆了啊
mq和他的小伙伴们
呆妞和小甜甜滑倒
by慢悠悠地运球,和yhr肘击时被裁判喊:我还没有发球,干啥呢
潜水员在mq大哥5犯罚下时,一边套衣服一边上场,下场大喊:我眼镜呢?
zr小朋友站在敌方战场上大喊射门
mq大哥在比赛结束时收获的来自朋友最真挚的祝福
以及,每一个在场下的五班人,在比赛终了的哨声中欢呼雀跃
明天会怎样我们谁都不知道
可是在今天,在此刻
五班劳道
是输是赢是眼泪是汗水是欢笑是痛苦都无法撼动的五班劳道
博学慎思
达济苍生
网结寰宇
霸唱天下
就是这样,喵~
最后一行献给所有五班的男神们偷偷表白mq大哥
以上是关于[最长回文子序列Manacher]4.11终于出线了啊!的主要内容,如果未能解决你的问题,请参考以下文章