• CF1326 D2. Prefix-Suffix Palindrome (Hard version) (manacher)


    题目链接

    https://codeforces.com/contest/1326/problem/D2

    题意

    给你一个字符串(S),找出最长的满足以下条件的字符串(T)

    • 长度不超过(S)
    • (T)为回文字符串
    • 存在两个字符串(a)(b)(可能为空),(T=a+b)(a)(S)的前缀,(b)(S)的后缀)

    思路

    假设(a)(b)有一个为空时,我们直接对整个(S)跑一遍(manacher),求出最长回文前缀和最长回文后缀,两者取最大。
    假设(a)(b)不为空,我们先对(S)进行首尾匹配,当匹配到不相同时,就截取剩下中间的那段字符串(c),跟上面一样,对(c)跑一遍(manacher),求出最长回文前缀和最长回文后缀并两者取最大,然后合并起来就是结果了。
    最后输出求出来的这两个字符串的长度最大的一个就好了

    #include<bits/stdc++.h>
    using namespace std;
    const int maxx = 3e6+10;
    char tmp[maxx];
    int len[maxx];
    int s1,s2;
    void Manacher(string s)
    {
    	tmp[0]='$';
    	tmp[1]='#';
    	int t=s.size();
    	for(int i=0;i<2*t+5;i++)len[i]=0;
    	for(int i=1;i<=t;i++)
            {
                tmp[2*i]=s[i-1];
                tmp[2*i+1]='#';
    	}
    	tmp[2*t+2]='';
    	int mx=0;
    	int mid;
    	for(int i=1;tmp[i];i++)
    	{
    		if(i<mx)len[i]=min(len[2*mid-i],mx-i);
    		else len[i]=1;
    		while(tmp[i-len[i]]==tmp[i+len[i]])len[i]++;
    		if(len[i]+i>mx)
    		{
    			mx=len[i]+i;
    			mid=i;
    		}
    		int l=len[i]-1;
    		if(i%2==0)
                    {
                        l=(l-1)/2;
                        int p=i/2;
                        if(p-l==1)s1=max(s1,len[i]-1);
                        if(p+l==t)s2=max(s2,len[i]-1);
                    }
                    else
                    {
                        l=l/2;
                        int p=(i-1)/2,q=(i+1)/2;
                        if(p-l+1==1)s1=max(s1,len[i]-1);
                        if(q+l-1==t)s2=max(s2,len[i]-1);
                    }
    	}
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            s1=0,s2=0;
            string s,ans1,ans2;
            cin>>s;
            int n=s.size();
            Manacher(s);
            if(s1>s2)ans1=s.substr(0,s1);
            else ans1=s.substr(n-s2);
            int i=0,j=n-1;
            while(i<j&&s[i]==s[j])ans2+=s[i],i++,j--;
            string ss=s;
            if(i<j)
            {
                s1=0,s2=0;
                ss=s.substr(i,j-i+1);
                int n=ss.size();
                Manacher(ss);
                if(s1>s2)ans2+=ss.substr(0,s1);
                else ans2+=ss.substr(n-s2);
            }
            ans2+=s.substr(j+1);
            if(ans1.size()>=ans2.size())cout<<ans1<<endl;
            else cout<<ans2<<endl;
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    顺流交易中,母公司销售部分存货,为什么收入也是全额抵消?
    借:递延所得税资产(负债)贷:所得税费用
    可变回报与固定回报
    或有对价
    可以税前扣除什么意思
    应收账款保理为什么是筹资活动
    外币报表折算差额计入其他综合收益
    分配现金股利为什么是筹资
    spring的@EnableAspectJAutoproxy注解
    Spring的@DeclareParents注解
  • 原文地址:https://www.cnblogs.com/HooYing/p/12531165.html
Copyright © 2020-2023  润新知