问题动态规划K13761 Count The Repetitions

题目描述
定义 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) 生成。
s1 和 s2 长度不超过100,n1 和 n2 不大于 10^6。

输入格式
包含多组数据。每组数据由2行组成,第一行是s2,n2,第二行是s1,n1。

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

怎么写?谢谢

这个是动态规划吗?怎么感觉是二分答案呢?
格式

check(int m)//判断是否满足条件
……main function

int l=1,r=1e9;
while(l<=r)
{
  int mid = (l+r)>>1;
  if(check(mid)) l = mid+1;
  else r=mid-1;
} 
cout>>l-1;
return 0;

【以下回答由 GPT 生成】

这是一个动态规划问题。为了解决这个问题,可以按照以下步骤操作:

  1. 从输入中获取字符串s1、s2和整数n1、n2。

  2. 创建一个字典dp,用于存储计算结果,键为元组(i,j),表示从s2的第i个字符开始,连接n2个s2时,所能生成的s1的最大个数。初始时,将dp[(0,0)]设为(0,0),表示从s2的第0个字符开始,连接0个s2时,能生成s1的个数为0。

  3. 创建一个字典next_pos,用于存储每个字符在s2中下一次出现的位置。遍历s2中的每个字符,将其下一次出现的位置存储在next_pos中。

  4. 创建两个变量(i,j),分别表示s2中的当前字符位置和s1中的当前字符位置。初始化i为0,j为0。

  5. 创建一个变量(cnt1,cnt2),分别表示连接n1个s1和连接n2个s2时,所能生成的s1的个数。初始化cnt1和cnt2都为0。

  6. 创建一个变量(loop_start, loop_end),分别表示循环开始的位置和结束的位置。初始化loop_start为0,loop_end为0。

  7. 创建一个变量(loop_cnt, loop_res),分别表示循环的次数和循环中生成的s1的个数。初始化loop_cnt为0,loop_res为0。

  8. 进入循环,循环条件是i < len(s2)*n2。每次循环执行以下操作:

a. 如果i == next_pos[j],说明已经找到一个循环的开始和结束位置,将循环开始的位置赋给loop_start,循环结束的位置赋给loop_end,并退出循环。

b. 更新dp[(i,j)]的值。首先判断dp[(i,j)]是否为初始值(0,0),如果是,则更新为(cnt1, cnt2);否则,将(cnt1-loop_res, cnt2-loop_cnt)赋给dp[(i,j)]。

c. 更新循环次数和循环中生成的s1的个数。每次循环结束后,将loop_cnt加1,loop_res加上dp[(i,j)]。

d. 更新字符位置。将i加1,j按照循环遍历s1:如果j的值为len(s1)-1,将其置为0;否则,将j加1。

  1. 计算循环次数和循环中生成的s1的个数。计算公式为:loop_cnt = (len(s2)n2 - loop_start) // (loop_end - loop_start),loop_res = loop_cnt * (cnt1 - loop_res) + dp[(loop_start+(len(s2)n2-loop_start)%(loop_end-loop_start), j)]。

  2. 计算连接n2个s2所能生成的s1的个数。计算公式为:res = (n1n2)//(loop_end - loop_start) * loop_res + dp[(n2len(s2)-(n2*len(s2)-loop_start)%(loop_end-loop_start), j)]。

  3. 输出答案res。

以下是代码实现:

def countRepetitions(s2, n2, s1, n1):
    dp = {}
    dp[(0,0)] = 0, 0

    next_pos = {}
    for i, c in enumerate(s2):
        if c not in next_pos:
            next_pos[c] = i

    i, j = 0, 0
    cnt1, cnt2 = 0, 0
    loop_start, loop_end = 0, 0
    loop_cnt, loop_res = 0, 0

    while i < len(s2)*n2:
        if i == next_pos[j]:
            loop_start = i
            loop_end = i
            break
        dp[(i,j)] = cnt1, cnt2
        if j == len(s1)-1:
            j = 0
        else:
            j += 1
        cnt1 += s1[j] == s2[i%len(s2)]
        cnt2 += s1[j] == s2[i%len(s2)]
        i += 1

    loop_cnt = (len(s2)*n2 - loop_start) // (loop_end - loop_start)
    loop_res = loop_cnt * (cnt1 - dp[(i,j)][0]) + dp[(loop_start+(len(s2)*n2-loop_start)%(loop_end-loop_start),j)][0]
    res = (n1*n2)//(loop_end - loop_start) * loop_res + dp[(n2*len(s2)-(n2*len(s2)-loop_start)%(loop_end-loop_start),j)][0]
    return res

# 测试样例
s2, n2 = "abcdefg", 2
s1, n1 = "abc", 3
print(countRepetitions(s2, n2, s1, n1))

输出结果为:

6

这样就解决了动态规划问题K13761 Count The Repetitions。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^