首页 > 其他分享 >力扣466

力扣466

时间:2023-11-10 12:56:42浏览次数:40  
标签:s2 s1 466 力扣 这题 答案 区间 倍增

 

定义 str = [s, n] 表示 strn 个字符串 s 连接构成。

  • 例如,str == ["abc", 3] =="abcabcabc"

如果可以从 s2 中删除某些字符使其变为 s1,则称字符串 s1 可以从字符串 s2 获得。

  • 例如,根据定义,s1 = "abc" 可以从 s2 = "abdbec" 获得,仅需要删除加粗且用斜体标识的字符。

现在给你两个字符串 s1 和 s2 和两个整数 n1n2 。由此构造得到两个字符串,其中 str1 = [s1, n1]str2 = [s2, n2]

请你找出一个最大整数 m ,以满足 str = [str2, m] 可以从 str1 获得。

  • 1 <= s1.length, s2.length <= 100
  • s1s2 由小写英文字母组成
  • 1 <= n1, n2 <= 106

上题和这题比起来。。
思路不要太清晰了
但是这题也是和上题一样,我看到的第一眼不知道我能够做写什么
因为感觉干什么都会直接T掉
这么看。。倍增我还是太不熟悉了
我不能敏锐的察觉出什么东西能够用倍增算出来,这才会觉得什么都干不了
看来倍增题写少了。。。
等弄完dp就去弄弄倍增吧
我似乎弄错了,我没有考虑到循环这个特征能够省略一些计算
然后倍增优化的状态设计特点是f[i,j]表示从i开始,2^j作为一个限制,或者是要求,有点类似背包的容量,能够干嘛干嘛,然后这个东西是能够累加的,而且是相对固定的一个东西,判断的规则不会受到起始点位置不同的影响
。。限制挺严格的其实

对于这题,就是设f[i][j]表示从str1的i位置开始,最少用几个字符才能合成str2*(2^j)

对于上题,就是设f[i][j]表示从城市i开始,走2^j天能够到达哪个位置

最重要的就是这个东西可以以相加的方式合并答案,然后有一个类似步数的东西在控制位置
模型建不起来。。不知道这一类的题目到底是什么样的,还是要写更多的题目才行
和区间dp的以“最后一次操作”作为划分点的题目一样。。只是会做这几题,还不够。要是做不到那种能够出题的阶段,遇到还是很容易写不出来

上一题的和这一题对应的一个特征是上一题在不同位置的时候,开车的法则是不变的,这一题则是str2总是在循环,配对的法则是没变的,所以这两题倍增的答案都能够相加

想了两天,现在大概是明白了。
主要是看到了这样一道题目https://www.luogu.com.cn/problem/P3147
这题,我看到的第一眼就很像区间dp
但是!它的n,是二十万
这是个n,别说是区间dp了,普通的O(n^2)也无法接受,O(n^3)就是天方夜谭
但是这是可以倍增优化的
这个题目和我之前遇到的一题十分相似,就是poj1390
同样是合并,同样是求一个最大值,这两题做法不一样的根本原因就是,poj1390中对同一段区间的合并先后顺序其实是在影响答案的优劣的
而在这题中,我对同一段区间,先合并某一对,还是后合并某一对,完全对答案的优劣没有任何的影响
这是完全不同的
也就是说,我们在这个题目中,设计的状态没有必要去考虑这个区间被组合是顺序,因为这个完全不会导致答案的不同
那我们就直接按照二进制进行组合不就好了?
这样就能够遍历过所有的可能的答案了

这其实就是倍增优化的适用区间
当我们在意的答案只收到区间大小的影响的时候或者在确定了起始位置和区间大小后,我们的答案就可以被确定时,倍增优化就是一个可行的选择
我们可以通过对每一个点,进行logn次计算,来得到这个点到后面2^i(0<=i<n)的位置的答案,再在第二遍中,用这个消息,来组合得到所有可能的答案
最终实现了O(nlogn)的下限复杂度
我目前看到的倍增优化都是遵循这个规则的。
不知道之后会不会遇到更多的特殊的倍增优化有其他的规则或者说是模型
附上代码  (没有数据测。。但是还是写了)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read() {
    char c=getchar();int a=0,b=1;
    for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
    for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
string s1,s2,s3;
int n1,n2;
ll f[105][32];
int main()
{
//    freopen(".in","r",stdin);
//    freopen(".out","w",stdout);
    getline(cin,s3);
    int flag=0;
    for(int i=0;i<s3.size();i++)
    {
        if(s3[i]=='"'&&flag==0)
        {
            flag=1;
        }
        if(flag==1&&s3[i]!='"')
        {
            s2+=s3[i];
        }
        if(flag==1&&s3[i]=='"')
        {
            flag=2;
        }
        if(flag==2&&s3[i]=='=')n2=s3[i+1]-'0';
        if(s3[i]=='"'&&flag==2)
        {
            flag=3;
        }
        if(flag==3&&s3[i]!='"')
        {
            s1+=s3[i];
        }
        if(flag==3&&s3[i]=='"')
        {
            flag=4;
        }
        if(flag==4&&s3[i]=='=')n1=s3[i+1]-'0';
    }
    cout<<s1<<' '<<n1<<' '<<s2<<' '<<n2<<endl;
    for(int i=0;i<s1.size();i++)
    {
        int pos=i;
        f[i][0]=0;
        for(int j=0;j<s2.size();j++)
        {
            int cnt=0;
            while(s1[pos]!=s2[j])
            {
                pos=(pos+1)%s1.size();
                if(++cnt>s1.size())
                {
                    cout<<"0"<<endl;
                    return 0;
                }
            }
            pos=(pos+1)%s1.size();
            f[i][0]+=cnt+1;
        }
    }
    for(int j=1;j<=30;j++)
    {
        for(int i=0;i<s1.size();i++)
        {
            f[i][j]=f[i][j-1]+f[(i+f[i][j-1])%s1.size()][j-1];
        }
    }
    ll m=0;
    for(int st=0;st<s1.size();st++)
    {
        ll x=st,ans=0;
        for(int k=30;k>=0;k--)
        {
            if(x+f[x%s1.size()][k]<=n1*s1.size())
            {
                x+=f[x%s1.size()][k];
                ans+=(1<<k);
            }
        }
        m=max(m,ans);
    }
    cout<<m/n2<<endl;
    return 0;
}

 

标签:s2,s1,466,力扣,这题,答案,区间,倍增
From: https://www.cnblogs.com/HLZZPawa/p/17815999.html

相关文章

  • 算法day1数组|力扣704二分查找,27移除元素
    数组基础理论数组是存放在连续内存空间上的相同类型数据的集合。可以通过下标轻松获取数据,但是增删元素的时候需要移动其他元素Vector和array的区别vector的底层实现是array,但是vector是容器不是数组数组的元素不能删除,只能覆盖小技巧:取中间intmid=l+r>>1;//有时候怕溢......
  • 力扣2149 暴力+另建两个vector<int>
    2149. 按符号重排数组解题思路另建两个容器,分别存储正负整数,然后依次正负相间放入numsclassSolution{public:vector<int>rearrangeArray(vector<int>&nums){intn=nums.size(),j=1;vector<int>a,b;for(autoi:nums){if(i<0)b.......
  • 力扣练习题
    1、week31.1、有效的括号20-有效的括号publicbooleanisValid(Strings){Deque<Character>stack=newDeque<>();char[]chars=s.toCharArray();for(charc:chars){if(c=='('||c=='['||c=='{&#......
  • 力扣2562 采用双指针
    2562. 找出数组的串联值classSolution{public://返回两数串联后的值longlongis(intm,intn){longlongans=n;inti=0;while(n){n/=10;i++;}returnans+m*pow(10,i);}longlon......
  • 力扣1370 直接模拟
    1370. 上升下降字符串按照题目模拟创建了一个长度为26的数组来存放字母数量kk是结果res的实时长度,cs是第几次(来决定添加最小的还是添加最大的)classSolution{public:stringsortString(strings){stringres;intarr[26]={0};intsize=26;......
  • 力扣905 按奇偶排序数组 C++ 双指针+一次遍历
    905.按奇偶排序数组classSolution{public:vector<int>sortArrayByParity(vector<int>&nums){inti=0,j=nums.size()-1;while(i<nums.size()-1&&i<j){while(i<j&&(nums[i]%2==0))i++;......
  • P1466 [USACO2.2] 集合 Subset Sums
    P1466USACO2.2集合SubsetSums毫无思路如果不告诉我这题是DP题,我一定会爆搜。看了题解,很妙。居然也能套背包板子。定义F[i][j]为在前\(i\)个数中选择一些数其和为\(j\)的方案总数。显然转移方程F[i][j]=F[i-1][j]+F[i-1][j-i]要么不选当前第\(i\)个数,要么选......
  • 力扣2610. 转换二维数组(哈希表)
    给你一个整数数组 nums 。请你创建一个满足以下条件的二维数组:二维数组应该 只 包含数组 nums 中的元素。二维数组中的每一行都包含 不同 的整数。二维数组的行数应尽可能 少 。返回结果数组。如果存在多种答案,则返回其中任何一种。请注意,二维数组的每一行上可以......
  • leetcode(力扣) 128. 最长连续序列(哈希)
    文章目录题目描述思路分析完整代码题目描述给定一个未排序的整数数组nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为O(n)的算法解决此问题。示例1:输入:nums=[100,4,200,1,3,2]输出:4解释:最长数字连续序列是[1,2,3,4]。......
  • 10道力扣题
    1.两数之和1.1暴力循环万物皆可使用循环破解。思路:两层循环,第一层找第一个变量,第二层找第二个变量。再判断两个变量之和是否与target相等,相等则返回下标。不等返回空数组。publicint[]twoSum(int[]nums,inttarget){for(inti=0,i<nums.length;i++){......