zoukankan      html  css  js  c++  java
  • Leecoder466 Count The Repetitons

    Leecoder466 Count The Repetitons

    题目大意

    定义([s,n])为连续(n)个串(s)构成的串

    现在给定(s_1,n_1,s_2,n_2),求最大的(m)满足([[s_2,n_2],m])([s_1,n_1])的子序列

    (|s_1|,|s_2| le 100,n_1,n_2le 10^6)

    首先,([s_2,n_2])我们是不能直接求出来的

    但是很明显([[s_2,n_2],m] = [s_2,n_2m])

    所以现在我们只需要求最大的(m')使得([s_2, m'])([s_1,n_1])的子序列

    那么就有

    [m = leftlfloor{frac{m'}{n_2}} ight floor ]

    我们发现,直接求(m')是不容易实现的,因为他的上界很大,可能到达$frac{|s_1| imes n_1}{n_2} $

    考虑把(m')二进制分解之后分位贪心

    (f_{i,j})表示从(s_1)的第(i)位开始匹配(2^j)(s_2)需要的字符个数

    那么则有

    [f_{i,j} = f_{i,j - 1} + f_{(i + f_{i,j - 1}) \% |s_1|,j - 1} ]

    至于(f_{i,0})我们可以使用最朴素的算法,直接暴力匹配,

    注意判断无解的情况直接输出(0)就好了

    这样我们就预处理完了

    求答案就直接暴力枚举开头位置

    然后利用倍增数组从高位向低位贪心,另外当前用了多少字符的初始值应该是(i)而不是(0)

    class Solution {
        int len1,len2;
        char s1[505],s2[505];
        long long f[31][505];
    public:
        int getMaxRepetitions(string S1, int n1, string S2, int n2) {
            memset(f,0,sizeof(f));
            len1 = S1.size();
            len2 = S2.size();
            for(int i = 0;i < len1;++i) s1[i] = S1[i];
            for(int i = 0;i < len2;++i) s2[i] = S2[i];
      //      printf("%d %d
    ",len1,len2);
            for(int i = 0;i < len1;++i){
                int pos = i;
                for(int j = 0;j < len2;++j){
                	int cnt = 0;
    				while(s1[pos] != s2[j]){
    					pos = (pos + 1) % len1;
    					if(++cnt >= len1) return 0;
    				}
    				pos = (pos + 1) % len1;
    				f[0][i] += cnt + 1;
                }
            }
          //  for(int i = 0;i < len1;++i)printf("%d ",f[0][i]);puts("");
            for(int j = 1;j <= 30;++j){
            	for(int i = 0;i < len1;++i){
    				f[j][i] = f[j - 1][i] + f[j - 1][(i + f[j - 1][i]) % len1];
    			}
            }
            long long ans = 0;
            for(int i = 0;i < len1;++i){
            	long long t = i,sum = 0;
            	for(int j = 30;j >= 0;--j){
            		if((t + f[j][t % len1]) <= (len1) * n1){
    					t += f[j][t % len1];
    					sum += 1 << j;
    				}
            	}
                //printf("%d %lld
    ",i,sum);
            	ans = max(ans,sum);
            }
            return ans / n2;
        }
    };
    
  • 相关阅读:
    1602液晶显示实验
    LNMP安装(二)
    LNMP安装(一)
    vim插件安装
    资料下载
    建表的sql
    time
    计算机里的加减乘除
    branch
    存储过程
  • 原文地址:https://www.cnblogs.com/wyxdrqc/p/11660110.html
Copyright © 2011-2022 走看看