迴文串——馬拉車(模板)

N - 最長迴文

給出一個只由小寫英文字符a,b,c…y,z組成的字符串S,求S中最長迴文串的長度.

迴文就是正反讀都是一樣的字符串,如aba, abba等

    Input
    輸入有多組case,不超過120組,每組輸入爲一行小寫英文字符a,b,c...y,z組成的字符串S 

兩組case之間由空行隔開(該空行不用處理)

字符串長度len <= 110000

    Output
    每一行一個整數x,對應一組case,表示該組case的字符串中所包含的最長迴文長度. 

求最長迴文子串

1.暴力求解

對於字符串的每一個點,分別左右遍歷判斷是否滿足str[i-t]==str[i+t];
這種方法時間複雜度太高,爲N^2。

2.Manacher.(線性複雜度)

設置變量:mx(當前位置時到達最右邊的迴文串位置),len[i]數組(記錄當前迴文串長度)id(當前最長迴文串的中點位置);
manacher算法與暴力算法不同之處是利用迴文串的特性即左右對稱,做了一個預處理;
len[i]=min(mx-i,len[2*id-i]);

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
const int N=223456;
char str[N],s[N];
int len[N];
int k;
void get_s(char s[])//將字符串預處理,消除奇數串或偶串的影響,填充與字符串不同的字符;
{
    k=0;
    str[k++]='@';
    str[k++]='#';
    int len=strlen(s);
    for(register int i=0;i<len;++i){
        str[k++]=s[i];
        str[k++]='#';
    }
    str[k]=0;
}
int manachar(char str[])
{
    int mx=0,id;         //mx初始化爲0;
    int maxx=-1;          //記錄最長的迴文串;
    for(register int i=1;i<k;++i){
        if(mx>i){                   //mx在i的右邊時,len[i]爲關於id對稱點的點,即len[i-2*(i-id)和mx與i的距離最小值];
            len[i]=min(mx-i,len[2*id-i]);
        }
        else len[i]=1;        //當mx<=i時,len[i]=1;
        while(str[i+len[i]]==str[i-len[i]]) ++len[i];  //拓展len[i]的長度,與暴力時一樣;
        if(len[i]+i>mx){            //更新mx和id的值;
            mx=len[i]+i;
            id=i;
            maxx=max(maxx,len[i]);
        }
    }
    return (maxx-1);
}
int main()
{
    while(~scanf("%s",s)){
        get_s(s);
        printf("%d\n",manachar(str));
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章