• 前缀和(P2697 宝石串)


    前言
    每次做出来什么本来做不出的题目,就忍不住记录一下。不过大多时候隔几天来看,就发现,啊,我当时只是做了一道这么弱智的题目呀,哈哈。前缀和确实不算太难。。

    传送门
    题目大意
    给你一个字符串只含G和R,求一个最长子串长度,使得两个字符的长度相等。(给的字符串长小于1e6)
    如:GRGGRG
    答案是:4。

    思路
    题目中字符串很长,暴力枚举显然不可能。
    但我们仔细一看,发现不过只有两个字符G和H。我们令G为1,令R为-1,那么GR的值就为0,这显然是一个可行的子串。

    那再看GRGGRG,我们开一个a数组记录前i个字符的值,那么
    a[0]=0,a[1]=1,a[2]=0,a[3]=1.a[4]=2,a[5]=1,a[6]=2。
    观察可得1~3是一个可行的子串(不包括1)
    1~5同样可行(不包括1)
    也就是说,当他们对应的a数组值相等时,中间的串必定可行,因为中间的串没有引起值的变化,那么G和R相等。
    那接下来我们该怎么做呢?
    我们可以用2个for循环枚举数组a,找出值相等并且下标相差最大的两个点即为最大子串,但这样复杂度过高。

    O(n)做法
    我们以DP的角度考虑一个优解,使得这个过程能在线性时间内完成。如对于可行的长度为2的子串,我们只需要记录出现最早的长度为2的下标和出现最晚的下标即可。这里结合代码理解:

    for(int i=0;i<str1.length();i++)
    	{
    		if(str1[i]=='G')
    			a[i+1]=a[i]+1;//计算a数组的值
    		else
    			a[i+1]=a[i]-1;
    		dp[a[i+1][1]=min(dp[a[i+1]][1],i+1);//记录最早
    		dp[a[i+1]][2]=max(dp[a[i+1]][2],i+1);//记录最晚
    	}
    

    但是新的问题又来了,a[i+1]可能是负数,数组可没有负数的下标!其实这并不难,我们把dp的第一维扩大一倍,把中间的下标当作原来的下标零来使用,像这样:

    //maxn=10000007
    for(int i=0;i<str1.length();i++)
    	{
    		if(str1[i]=='G')
    			a[i+1]=a[i]+1;
    		else
    			a[i+1]=a[i]-1;
    		dp[a[i+1]+maxn+1][1]=min(dp[a[i+1]+maxn+1][1],i+1);
    		dp[a[i+1]+maxn+1][2]=max(dp[a[i+1]+maxn+1][2],i+1);
    	}
    

    完整代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1000009;
    int a[2*maxn];
    string str1;
    int dp[maxn*2+9][3];
    int main()
    {
    	cin>>str1;
    	for(int i=0;i<=maxn*2-5;i++)
    		dp[i][1]=100000000;//为min作预处理
    	dp[maxn+1][1]=0;//这里可以把maxn+1看作原来的下标0
    	for(int i=0;i<str1.length();i++)
    	{
    		if(str1[i]=='G')
    			a[i+1]=a[i]+1;
    		else
    			a[i+1]=a[i]-1;
    		dp[a[i+1]+maxn+1][1]=min(dp[a[i+1]+maxn+1][1],i+1);
    		dp[a[i+1]+maxn+1][2]=max(dp[a[i+1]+maxn+1][2],i+1);
    	}
    	int sumn=0;
    	for(int i=0;i<=maxn+str1.length();i++)//注意,从下标0开始
    		sumn=max(sumn,dp[i][2]-dp[i][1]);
    	cout<<sumn;
    }
    

    感谢dalao过目!

  • 相关阅读:
    Vue打包之后部署到 express 服务器上
    Vue 点击事件传递原生DOM事件?
    CSS hover 改变另外一个元素状态
    element-UI el-table二次封装
    element-UI el-table添加序号列时序号永远都是从1开始?
    element-UI el-table表格根据搜索条件表格值改变颜色
    HTML head meta标签详细
    CodeForces 489C Given Length and Sum of Digits... (dfs)
    CodeForces 489B BerSU Ball (水题 双指针)
    Codeforces 489A SwapSort (水题)
  • 原文地址:https://www.cnblogs.com/iss-ue/p/12679635.html
Copyright © 2020-2023  润新知