题解 UVA11475 【Extend to Palindrome】

题目链接

Solution Extend to Palindrome

题目大意:给定一个字符串\(S\),你需要求字符串\(S^*\),满足\(S\)\(S^*\)的前缀,\(S^*\)是个回文子串,在这前提下使得\(S^*\)长度尽量小

\(Manacher\),贪心


分析:

既然\(S\)\(S^*\)的前缀,那么\(S^*\)可以看做由\(S\)末尾追加一个字符串得来,我们要使得这个追加字符串的长度尽量小

由于回文串的性质,追加字符串对应\(S^*\)的前缀,我们要使追加字符串长度尽量小就要使得这个前缀的长度尽量小,于是我们在\(S\)中找是\(S\)的后缀的最长回文子串即可

然后就是\(Manacher\)板子了

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e6 + 100;
char org[maxn],str[maxn],ans[maxn];
int len[maxn],n,siz;
inline void init(){
    str[siz = 0] = '$';
    for(int i = 1;i <= n;i++)
        str[++siz] = '#',str[++siz] = org[i];
    str[++siz] = '#';
    str[siz + 1] = '?';
}
inline void manacher(){
    int pos = 0,mx = 0;
    for(int i = 1;i <= siz;i++){
        if(i < mx)len[i] = min(mx - i,len[2 * pos - i]);
        else len[i] = 1;
        while(str[i - len[i]] == str[i + len[i]])len[i]++;
        if(i + len[i] > mx){
            mx = i + len[i];
            pos = i;
        }
    }
}
inline void solve(){
    n = strlen(org + 1);
    init();
    manacher();
    int i;
    for(i = 1;i <= siz && i + len[i] - 1 != siz;i++);
    memcpy(ans,str,sizeof(char) * (siz + 1));
    ans[0] = '\0';
    for(int delta = 0;i - delta >= 0;delta++)
        ans[i + delta] = ans[i - delta];
    for(i = 1;ans[i] != '\0';i++)
        if(ans[i] != '#')putchar(ans[i]);
    putchar('\n');
}
int main(){
    while(~scanf("%s",org + 1))solve();
    return 0;
} 

猜你喜欢

转载自www.cnblogs.com/colazcy/p/11808323.html
今日推荐