Codeforces Global Round 7 D2 - Prefix-Suffix Palindrome (Hard version)(马拉车算法)

题目链接
在这里插入图片描述
思路:不知道为什么比赛的时候作死哈希,最后还被fst了呜呜呜。
其实比赛的时候也想到了马拉车,但马拉车的题没怎么练过,有点生手,马拉车里p【i】表示的是i这个位置的回文半径,那么要找它的最长回文前缀的话就判断一下i-p【i】是否等于0,i+p【i】是否能到达字符串尾就行了,相当的简单。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+1;
char s[maxn];
void Manacher(string s) {
    string t = "$#";
    for (int i = 0; i < s.size(); ++i) {
        t += s[i];
        t += "#";
    }
    vector<int> p(t.size(), 0);
    int mx = 0, id = 0, resLen = 0, resCenter = 0;
    for (int i = 1; i < t.size(); ++i) {
        p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
        while (t[i + p[i]] == t[i - p[i]]) ++p[i];
        if (mx < i + p[i]) {
            mx = i + p[i];
            id = i;
        }
        if(i-p[i]<=0||i+p[i]-1>=t.size()-1)
        if (resLen < p[i]) {
            resLen = p[i];
            resCenter = i;
        }
    }
    for(int i=resCenter-resLen+1;i<=resCenter+resLen-1;++i)
    if(t[i]>='a'&&t[i]<='z') cout<<t[i];
}
 
int main() {
	int T; 
    scanf("%d",&T);
    while(T--)
    {
    	string str,str1;
    	scanf("%s",s+1);
    	int left=1,len=strlen(s+1);
    	while(left<=(len/2)&&s[left]==s[len-left+1]) str+=s[left++];
    	cout<<str;
		for(int i=left;i<=len-left+1;++i)  str1+=s[i];
		Manacher(str1);
		for(int i=left-1;i>=1;--i) printf("%c",s[i]);
		printf("\n");
	}
}
发布了283 篇原创文章 · 获赞 0 · 访问量 7320

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/104998589