zoukankan      html  css  js  c++  java
  • Manacher算法--Poj3974

    https://subetter.com/algorithm/manacher-algorithm.html

    p[i]=min(p[j],mx-i)
    即p[i]为后面两者间的较小值,如果强行给它较大值,都将引发另一个值的变大。例如当
    p[j]大于mx-i时。如果p[i]=p[j],将使得p[mx]变大(而事实上p[j],p[mx]都是固定值)
    这对于第一种情况:
    J有一部分是越过id回文串的左边界的,则i的回文串是不能超过id的右边界。如果越过即p[i]=p[j]则
    d=c..以i为回文
    b=c..以id为回文
    b=a..以j为回文
    于是乎a=d..说明id的回文还能放大,这是不允许的

    对于第二种情况
    当p[j]<mx-i时,如果强行将i=mx-i的话,则会出现
    d=c...关于i对称
    c=b...关于id对称
    a=d...关于id对称
    于是a=b,因而p[j]变大
    (图中关于a,d的红线不应该划得超过黑线,应与之相等)

    #include<bits/stdc++.h>
    #define N 2050001
    using namespace std;
    int len,p[N],Case,ans;
    char ch[N],s[N*2];
    void manacher()
    {
        int cnt=1;s[0]='%';s[1]='#';
        for(int i=0;i<len;i++)
    	{
            s[++cnt]=ch[i];
            s[++cnt]='#';
        }
        //在原串的基础上,在字符最开始加一个上"$",然后让每个字符的前后都是"#"
    	//例如abc----->$#a#b#c#,于是len2的值为2*len1+2 
        int maxRight=0,id=0;
        for(int i=1;i<=cnt;i++)
    	
    	{
            if(i<maxRight)
    		    p[i]=min(p[2*id-i],maxRight-i);
    		    //p[2*id-i]是i关于id对称的另一个点,这个点的P值已算出来过
    			//maxright-i为i到maxright的距离
    			//取其两者较小值 
    		else 
    		     p[i]=1;
            while (i+p[i]<=cnt&&s[i-p[i]]==s[i+p[i]])
                  p[i]++;
            if(i+p[i]>maxRight) 
    		      id=i,maxRight=i+p[i];
        }
        for(int i=1;i<=cnt;i++)
    	     ans=max(ans,p[i]);
        ans--;
    }
    int main(){
        while(1){
            scanf("%s",ch);len=strlen(ch);
            if(len==3&&ch[0]=='E'&&ch[1]=='N'&&ch[2]=='D')break;
            memset(p,0,sizeof(p));
            ans=1;manacher();
            printf("Case %d: %d
    ",++Case,ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    求转置矩阵问题
    喷水装置
    面试之谈
    迭代任意8种数据类型数组
    Session那点事
    随机验证码
    正则表达式:网页爬虫
    模拟上传服务端
    Properties集合的练习
    用递归算法对指定目录的深度遍历
  • 原文地址:https://www.cnblogs.com/cutemush/p/12369518.html
Copyright © 2011-2022 走看看