• Acwing 294.计算重复 (倍增优化DP)


    题目

    定义 conn(s,n) 为 n 个字符串 s 首尾相接形成的字符串,例如:

    conn(“abc”,2)=”abcabc”
    称字符串 a 能由字符串 b 生成,当且仅当从字符串 b 中删除某些字符后可以得到字符串 a。

    例如“abdbec”可以生成“abc”,但是“acbbe”不能生成“abc”。

    给定两个字符串 s1 和 s2,以及两个整数 n1 和 n2,求一个最大的整数 m,满足conn(conn(s2,n2),m) 能由 conn(s1,n1) 生成。

    输入格式
    输入包含多组测试数据。

    每组数据由2行组成,第一行包含s2,n2,第二行包含s1,n1。

    输出格式
    对于每组数据输出一行表示答案m。

    数据范围
    s1 和 s2 长度不超过100,n1 和 n2 不大于 106。

    输入样例:
    ab 2
    acb 4
    acb 1
    acb 1
    aa 1
    aaa 3
    baab 1
    baba 11
    aaaaa 1
    aaa 20
    输出样例:
    2
    1
    4
    7
    12

    思路

    是一道倍增dp,可以匹配的最大字串个数。1e6的数据量并不算小了,那么我们考虑从s1的每个字母尝试去匹配s2,并用数组记录长度,考虑到倍增的思想,所以我们这里记录的都是匹配2的某次方个s2所需长度,然后从倒序枚举2的次方,依次加入,当这个长度大于母串长度就退出,最后的答案是长度对被匹配串的长度相除下取整。

    代码实现

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    typedef pair<int ,int> PII;
    ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
    inline int read() {
        char ch=getchar(); int x=0, f=1;
        while(ch<'0'||ch>'9') {
            if(ch=='-') f = -1;
            ch=getchar();
        } 
        while('0'<=ch&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        }   return x*f;
    }
    
    const int maxn=110,M=31;
    string s1,s2;
    int n1,n2;
    ll dp[maxn][M];
    
    
    int main () {
    //    freopen ("data.in","r",stdin);
       while (cin>>s2>>n2>>s1>>n1) {
           int sz=s1.size ();
           
           bool fail=false;
           rev (i,0,sz) {
               int p=i;
               dp[i][0]=0;
               rev (j,0,s2.size ()) {
                   int cnt=0;
                   while (s1[p]!=s2[j]) {
                       p=(p+1)%sz;
                       cnt++;
                       if (cnt>sz) {
                           fail=true;
                           break;
                       }
                   }
                   if (fail) break;
                   p= (p+1)%sz;
                   dp[i][0]+=cnt+1;
               }
               if (fail) break;
           }
           if (fail) {
               cout<<0<<endl;
               continue;
           }        
    
           rep (j,1,30) 
             rev (i,0,sz) {
                 dp[i][j]=dp[i][j-1]+dp[(i+dp[i][j-1])%sz][j-1];
             }
    
            ll ans=0;
            rev (i,0,sz) {
                ll p=i,t=0;
                per (k,30,0) 
                   if (p+dp[p%sz][k]<=sz*n1) {
                       p+=dp[p%sz][k];
                       t+=1<<k;
                   }
                   ans=max (ans,t);
            }
            cout<<ans/n2<<endl;
       }   
    
    //    fclose (stdin);
       return 0;
    }
    
    
  • 相关阅读:
    Stage划分原理
    Spark转换和动作算子
    Spark运行原理
    Scrapy数据持久化
    在实际工作中Eclipse常用的快捷键
    关于Linux(CentOS6.5)中文输入法、中文桌面可视化等问题
    Eclipse无法启动报An internal error occurred during: "reload maven project". java.lang.NullPointerExceptio错原因及解析
    在Eclipse中复制导入项目并且修改原来的项目名字,项目后面的括号显示原来项目的名字!
    response.sendRedirect()与request.getRequestDispatcher("/index.jsp").forward(request, response)两者辨析
    MyEclipse/Eclipse导出jar方法
  • 原文地址:https://www.cnblogs.com/hhlya/p/13473175.html
Copyright © 2020-2023  润新知