• HDU 3613 Best Reward Manacher算法


    HDU 3613 Best Reward Manacher算法

    题意

    字符串,需要把这个字符串分成两段,并使得被分开的两段价值和最大。

    一个串如果是回文,那么它的价值就是所有字符的价值和,否则价值为0。每个字母都有相应的价值,这个会给出。

    解题思路

    使用Manacher,我们可以算出每个点的回文串长度,然后我们枚举左半部分的长度(这样很容易算出中心点),进而知道以这个中心点的回文串长度是不是等于这个左半部分的长度。这样来判断。

    对于价值,我们可以使用前缀和来提前算好,这样用的话就可以直接用了。下节的代码实现对应这个算法。

    搜了一下题解,还有发现使用拓展KMP也可以,思路上也比较简单。
    想要看的话可以点击这个链接:https://blog.csdn.net/u013480600/article/details/23041391

    代码实现

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int inf=0x3f3f3f3f;
    const int maxn=5e5+7;
    char str[maxn], s[maxn<<1];
    int p[maxn<<1], newlen;
    int val[26], presum[maxn];
    void init(int n)
    {
    	newlen=n<<1;
    //	s[0]='$';
    	for(int i=0; i<=newlen+1; i++) s[i]='#';
    	for(int i=1; i<=n; i++) s[i<<1]=str[i];
    	s[newlen+2]=0;
    }
    void manacher()
    {
    	int mx=0,id=0;
    	for(int i=1;i<=newlen;i++)
    	{
    		if(mx>i) p[i]=min(p[2*id-i],mx-i);
    		else p[i]=1;
     
    		while(i-p[i]>=0&&s[i-p[i]]==s[i+p[i]]) p[i]++;
    		if(i+p[i]>mx) 
    		{
    			mx=i+p[i];
    			id=i;
    		}
    	}
    }
    int main()
    {
    	int t=0;
    	scanf("%d",&t);
    	while(t--)
    	{
    		for(int i=0; i<26; i++)	scanf("%d", &val[i]);
    		scanf("%s", str+1);
    		int len=strlen(str+1);
    		presum[0]=0;
    		for(int i=1; i<=len; i++)
    			presum[i] = presum[i-1] + val[ str[i]-'a'];
    		init(len);
    		manacher();
    //		for(int i=1; i<=newlen; i++)
    //			printf("%d ", p[i]);
    //		printf("
    ");
    		int ans=-inf;
    		for(int cut=1; cut<len; cut++)
    		{
    			int temp=0;
    			int len1=cut, len2=len-len1;
    			if(len1%2 == 1)
    			{
    				int mid=len1/2+1;
    				int palen=p[mid<<1]-1; //mid<<1,这里是对应的实际位置 
    				if(len1 == palen) temp+=presum[len1]; 
    			}
    			else 
    			{
    				int mid=len1/2;
    				int palen=p[mid*2+1]-1;
    				if(len1 == palen ) temp+=presum[len1];
    			}
    			if(len2%2==1)
    			{
    				int mid=len1+len2/2+1;
    				int palen=p[mid<<1]-1;
    				if(len2 == palen) temp += presum[len] - presum[len1];
    			}
    			else 
    			{
    				int mid=len1+len2/2;
    				int palen=p[mid*2+1]-1;
    				if(len2 == palen ) temp += presum[len] - presum[len1];
    			}
    			if(temp>ans) ans=temp;
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Linux配置SSH公钥认证与Jenkins远程登录进行自动发布
    在阳台上种花生
    已知传递函数,求幅频响应?
    win8快速锁屏
    word2016怎么让目录索引显示在左边?
    Matlab 瑞利信道仿真
    rayleighchan实现瑞利多径衰落信
    2017电商趋势
    【连载7】二手电商平台的账号与信用体系
    【连载6】二手电商APP的导购功能与关系链机制分析
  • 原文地址:https://www.cnblogs.com/alking1001/p/12248658.html
Copyright © 2020-2023  润新知