HDU 4513 迴文串Manacher演算法

來源:互聯網
上載者:User

Manacher演算法學習: http://blog.csdn.net/vsooda/article/details/8725580

代碼1:轉自http://blog.csdn.net/sprintfwater/article/details/8709458

#include <stdio.h>#include <string.h>#include <stdlib.h>#define MAXN 100005int a[MAXN * 2];struct Rem{int left;int right;}rem;int odd[2 * MAXN]; //儲存每個元素為中心的迴文對數int min(int a, int b){return (a < b) ? a : b;}int fun(int i, int m, int N) //嘗試對外繼續擴張{int l = i - m - 1, r = i + m + 1;int ret = 0;for(;(l > 0)&&(r <= N);--l, ++r){if((a[r] == -1) ||  ((a[l] == a[r]) && ((r - l == 2)||(a[r] <= a[r - 2])  )))++ret;else break;}return ret;}int main(){int T, N;for(scanf("%d", &T); T--; ){scanf("%d", &N);int i = 0;a[++i] = -1;while(N--){scanf("%d", &a[++i]);a[++i] = -1;}N = i;rem.left = rem.right = 0;int ans = 1;memset(odd, 0, sizeof(odd));for(int i = 1; i <= N; ++i){int m = 0;if(rem.right > i)m = min(rem.right - i, odd[rem.left + (rem.right - i)]);//利用對稱左右對稱性質最佳化odd[i] = m + fun(i, m, N);if(i + odd[i] > rem.right)//當有最大右邊覆蓋,記錄下來{rem.left = i - odd[i];rem.right = i + odd[i];}if(odd[i] > ans)ans = odd[i];}printf("%d\n", ans);}return 0;}

代碼2:轉自http://hi.baidu.com/chenwenwen0210/item/51b72039793833f56d15e9ba

#include<stdio.h>#include<math.h>#include<string.h>#include<map>#include<algorithm>#include<queue>using namespace std;typedef __int64 lld;  const int MAX=110000*2;int str[MAX];//原字串int sb[MAX];int p[MAX];//表示以i為中心的迴文半徑,/*p[i]-1剛好是原字串以第i個為中心的迴文串長度。畫畫圖就知道了,因為兩端配匹的肯定是字元g*//*Mancher主演算法。功能:求出以i為中心的迴文半徑p[i];參數:傳入構造好的字串長度特殊說明:因為前面加了一個無效字元,所以下標從1開始。例題:http://acm.hdu.edu.cn/showproblem.php?pid=3068http://poj.org/problem?id=3974http://acmpj.zstu.edu.cn/JudgeOnline/showproblem?problem_id=3780http://acmpj.zstu.edu.cn/JudgeOnline/showproblem?problem_id=3769http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=12581#problem/Ahttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3661http://acm.hdu.edu.cn/showproblem.php?pid=3948*/bool dig(char x){return x>='0'&&x<='9';}int getval(){    int ret=0,sign=1;    char c;    while(!dig(c=getchar())&&c!='-');    if(c=='-')sign=-1;    else ret=c-'0';    while(dig(c=getchar()))ret=ret*10+c-'0';    return ret*sign;}void Manacher(int n){    int i;    int mx=0;//記錄前面迴文串最長影響到的地方。不一定是最長迴文串造成的。    int id;//最長影響串的ID;    p[0]=0;    for(i=1;i<n;i++)    {        p[i]=1;//至少是1        if(mx>i)//i受到影響即,id+p[id]-1>=i;        {            p[i]=p[2*id-i];//2*id-i是i關於id的對稱點相當於是id-(i-id);            if(mx-i<p[i])p[i]=mx-i;            //由於對稱點的迴文半徑可能超過mx-i,因為mx後面的還沒有配過            //所以要取小的。等等繼續配        }          //向兩端配匹        while(str[i-p[i]]==str[i+p[i]])        {            if(str[i+p[i]]==1)            {                p[i]++;            }            else            {                int a=i-p[i];                int b=i+p[i];                  if(a+2<=b-2&&str[a]<=str[a+2]&&str[b-2]>=str[b])                {                    p[i]++;                    continue;                }                else if(a==b)                {                    p[i]++;                    continue;                }                else if(a+2>b-2)                {                    p[i]++;                    continue;                }                                break;            }        }          if(i+p[i]>mx)        {            mx=i+p[i];            id=i;        }    }}  /*功能:構造字串,在每一個字元前插入一個,g,一般用'#'第一個字元前面再插入,first,一般用'$'最後再插入g字元總之不是在輸入中出現的字元就行了。比如abb,構造成$#a#b#b#參數:<first,第一個字元>,<g,一般字元>  傳回值:構造好的字串長度*/int pre(int first,int g,int m){    int i,n=0;    memcpy(sb,str,sizeof(int)*(m+2));    str[0]=first;    n++;    for(i=0;i<m;i++)    {        str[n++]=g;        str[n++]=sb[i];    }      str[n++]=g;    str[n]=3;    return n;}int main(){    int n;    int i;    int CS=1;    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        for(i=0;i<n;i++)        {            //scanf("%d",&str[i]);            str[i]=getval();        }        n=pre(0,1,n);        Manacher(n);        int ans=0;          for(i=1;i<n;i++)        {            if(p[i]>ans)ans=p[i];        }          printf("%d\n",ans-1);    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.