题意:给一个字符串,在后面添加最少的字符,使它变成回文串。
思路:显然要找出后缀最长的回文子串,然后加上前面的部分即可,我们可以考虑用字符串哈希或kmp匹配,将后往前和前往后的子串匹配一下,相同的就是回文串。
①使用滚动哈希的方法,复杂度O(n)。
# include <iostream> # include <cstdio> # include <cstring> # define ULL unsigned long long using namespace std; int main() { char s[100003]; while(~scanf("%s",s)) { ULL pow=1, seed=233, pre=0, suf=0, ans; int len = strlen(s); for(int i=len-1; i>=0; --i) { suf = suf + s[i]*pow; pow *= seed; pre = pre*seed + s[i]; if(suf == pre) ans = i; } printf("%s",s); for(int i=ans-1; i>=0; --i) putchar(s[i]); printf("\n"); } return 0; }
②KMP算法,比hash略慢。
# include <iostream> # include <cstdio> # include <cstring> # include <algorithm> using namespace std; string s, t; int pre[100003]; void init() { pre[0] = pre[1] = 0; for(int i=1; i<t.size(); ++i) { int j = pre[i]; while(j && t[j] != t[i]) j = pre[j]; pre[i+1] = t[j]==t[i]?j+1:0; } } int main() { while(cin >> s) { int j=0; t.resize(s.size()); reverse_copy(s.begin(), s.end(), t.begin()); init(); for(int i=0; i<s.size(); ++i) { while(j && s[i] != t[j]) j = pre[j]; if(s[i] == t[j]) ++j; } cout << s << t.substr(j) << endl; } return 0; }