bzoj2565最大双回文串

来源:互联网 发布:淘宝联盟怎么做高佣 编辑:程序博客网 时间:2024/06/05 23:57

Description

  
  顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
  输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分XY,(|X|,|Y|≥1)且XY都是回文串。

Input

一行由小写英文字母组成的字符串S

Output

  一行一个整数,表示最长双回文子串的长度。

Sample Input

baacaabbacabb

Sample Output

12

HINT

样例说明

  从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。

数据规模及限制

  对于10%的数据,2≤|S|≤103。

  对于30%的数据,2≤|S|≤104。

  对于100%的数据,2≤|S|≤105。

 昨天看了stringoier的论文,学习了manacher的算法,这个算法的神奇之处在于避免了许多不必要的 操作。而这一题恰巧也灵活的使用了这个算法的思想。我最初的思想是

搞一个lef数组记录以当前点为结尾的最长回文串,rig数组记录以当前点为开头的最长回文串,时间复杂度O(n*n)

代码如下

 for(i=1;i<len;i++)

   {
       for(j=i;j<i+r[i];j++)
       {
          temp=j-i+1;
         if(temp>left[j])
                   left[j]=temp;
         }
       for(j=i;j>i-r[i];j--)
       {
             temp=i-j+1;
             if(temp>rig[j])
                   rig[j]=temp;
       }
   }
   for(i=1;i<len-1;i++)
        if(left[i]+rig[i+1]-1>ans)
            ans=left[i]+rig[i+1]-1;
后来无耻看了strongoier的论文和博客,以求lef数组为例,他维护了一个走的最右的区域,如果以当前点为中心的回文串没有先前点的回文串长,则没必要更新

代码如下

for(i=1,j=3;i<len;i++)

       for(;j<i+r[i];j++)
          // if(b[j]=='#')
                c[j]=j-i;
   for(i=len-1,j=len-2;i>=1;i--)
        for(;j>=i-r[i]+1;j--)
           if(c[j])
                c[j]+=i-j;
   for(i=1;i<len;i++)
        if(c[i]>ans)
            ans=c[i];


0 0
原创粉丝点击