您的位置:首页 > 其它

UVA - 11475 Extend to Palindrome manacher+贪心

2017-02-16 18:39 337 查看


E - Extend to Palindrome

 UVA
- 11475

Your task is, given an integer N, to make a palidrome (word that reads the same when you reverse it) of length at least N. Any palindrome will do. Easy, isn’t it? That’s what you thought before you passed it on to your inexperienced team-mate. When the contest
is almost over, you find out that that problem still isn’t solved. The problem with the code is that the strings generated are often not palindromic. There’s not enough time to start again from scratch or to debug his messy code. Seeing that the situation
is desperate, you decide to simply write some additional code that takes the output and adds just enough extra characters to it to make it a palindrome and hope for the best. Your solution should take as its input a string and produce the smallest palindrome
that can be formed by adding zero or more characters at its end.

Input

Input will consist of several lines ending in EOF. Each line will contain a non-empty string made up ofupper case and lower case English letters (‘A’-‘Z’ and ‘a’-‘z’). The length of the string will be less thanor equal to 100,000.

Output

For each line of input, output will consist of exactly one line. It should contain the palindrome formedby adding the fewest number of extra letters to the end of the corresponding input string.

Sample Input

aaaa

abba

amanaplanacanal

xyz

Sample Output

aaaa

abba

amanaplanacanalpanama

xyzyx

Source

UVA - 11475

My Solution

题意:给出一个字符串,在末尾添加尽可能少的字符串,使这个新字符串为回文串,输出新字符串。

manacher+贪心

先用manacher O(n)的跑出原字符串的以每个i为中心的回文子串,

然后应该自己得出的一个manacher的结论if(len[i + j] >= (j - i)/2 + 1) 则字符串s[i......j]为回文子串。

也就是从原串的右边开始,向左跑,找到以sz-1为右端点的最大回文子串,标记为ans开始,则输出原串后,从ans-1开始到0按照顺序每个字符依次输出。

复杂度 O(n)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 8;

int len[2*maxn];
char str[maxn];

void manacher(int n)
{
int p, q, r;
len[0] = 1;
for(int i = 1, j = 0; i < (n << 1) - 1; i++){
p = i >> 1, q = i - p, r = ((j + 1) >> 1) + len[j] - 1;
len[i] = r < q ? 0 : min(r - q + 1, len[(j << 1) - i]);
while(p > len[i] - 1 && q + len[i] < n && str[p - len[i]]
== str[q + len[i]])
len[i]++;
if(q + len[i] - 1 > r)
j = i;
}
}

int main()
{
#ifdef LOCAL
freopen("e.txt", "r", stdin);
//freopen("e.out", "w", stdout);
#endif // LOCAL
int sz, i, j, ans;
while(scanf("%s", str) != EOF){
sz = strlen(str); ans = sz - 1;
manacher(sz);
for(i = sz - 2, j = sz - 1; i >= 0; i--){
if(len[i + j] >= (j - i)/2 + 1){
ans = i;
}
}
printf("%s", str);
for(i = ans - 1; i >= 0; i--) putchar(str[i]);
putchar('\n');
}
return 0;
}



  Thank you!

                                                                                                           
                                 ------from ProLights
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: