zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
  • 相关阅读:
    JavaScript操作符instanceof揭秘
    Linux打开txt文件乱码的解决方法
    Working copy locked run svn cleanup not work
    poj 2299 UltraQuickSort 归并排序求解逆序对
    poj 2312 Battle City 优先队列+bfs 或 记忆化广搜
    poj2352 stars 树状数组
    poj 2286 The Rotation Game 迭代加深
    hdu 1800 Flying to the Mars
    poj 3038 Children of the Candy Corn bfs dfs
    hdu 1983 Kaitou Kid The Phantom Thief (2) DFS + BFS
  • 原文地址:https://www.cnblogs.com/hhlya/p/13473175.html
Copyright © 2011-2022 走看看