zoukankan      html  css  js  c++  java
  • [bzoj] 2565 最长双回文串

    原题

    双回文串的定义是“回文串回文串”,所以答案就是以i结尾的最长回文串长度加上以i+1为开头的最长回文串的长度

    然而怎么处理作为结尾时的长度和作为开头时的长度呢?n^2肯定是不行的啊!

    Eg:求结尾数组
    对于当前i结尾的ans,一定越早更新他的越长,所以像manacher一样,记录一个右端点,如果i>maxr那么暴力更新,否则不用更新。而且每个位置只用被更新一遍,也就是O(n)的了
    开头数组是同理的

    #include<cstdio>
    #include<algorithm>
    #define N 200010
    using namespace std;
    int l=1,now,ans,lft[N],rght[N],a[N],mxr,p;
    char s[N],c;
    
    int main()
    {
        s[0]='@';
        while (~scanf("%c",&c))
        {
    	if (c=='
    ') break;
    	s[l++]='#';
    	s[l++]=c;
        }
        s[l++]='#';
        s[l++]='?';
        for (int i=1,q;i<=l;i++)
        {
    	if (mxr>i) q=min(mxr-i,a[2*p-i]);
    	else q=1;
    	while (s[i-q]==s[i+q]) q++;
    	a[i]=q;
    	if (i+q>mxr) mxr=i+q,p=i;
        }
        for (int i=1;i<=l;i++)
        {
    	if (i+a[i]>now)
    	{
    	    for (int j=now+1;j<=i+a[i];j++)
    		if (s[j]!='#') lft[j]=j-i+1;
    	    now=i+a[i]-1;
    	}
        }
        now=l-1;
        for (int i=l-1;i>=1;i--)
        {
    	if (i-a[i]<now)
    	{
    	    for (int j=now-1;j>=i-a[i];j--)
    		if (s[j]!='#') rght[j]=i-j+1;
    	    now=i-a[i]+1;
    	}
        }
        for (int i=2;i<=l;i+=2)
    	if (s[i]!='#') ans=max(ans,lft[i]+rght[i+2]);
        printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    leetcode 1. 两数之和
    leetcode 671. 二叉树中第二小的节点
    leetcode 100. 相同的树
    leetcode 110. 平衡二叉树
    leetcode 144. 二叉树的前序遍历
    1066. Root of AVL Tree (25)
    leetcode 100 相同的树
    leeCode 515 在每个树行中找最大值
    LeetCode 31.下一个排列
    面向对象UML中类关系
  • 原文地址:https://www.cnblogs.com/mrha/p/7879698.html
Copyright © 2011-2022 走看看