CodeForce-476E-Dreamoon and Strings

版权声明:欢迎评论与转载,转载时请注明出处! https://blog.csdn.net/wjl_zyl_1314/article/details/83511276

原题
Dreamoon has a string s and a pattern string p. He first removes exactly x characters from s obtaining string s’ as a result. Then he calculates that is defined as the maximal number of non-overlapping substrings equal to p that can be found in s’. He wants to make this number as big as possible.
More formally, let’s define as maximum value of over all s’ that can be obtained by removing exactly x characters from s. Dreamoon wants to know for all x from 0 to |s| where |s| denotes the length of string s.
Input
The first line of the input contains the string s (1 ≤ |s| ≤ 2 000).
The second line of the input contains the string p (1 ≤ |p| ≤ 500).
Both strings will only consist of lower case English letters.
Output
Print |s| + 1 space-separated integers in a single line representing the for all x from 0 to |s|.
Examples
Input
aaaaa
aa
Output
2 2 1 1 0 0
Input
axbaxxb
ab
Output
0 1 1 2 1 1 0 0
Note
For the first sample, the corresponding optimal values of s’ after removal 0 through |s| = 5 characters from s are {“aaaaa”, “aaaa”, “aaa”, “aa”, “a”, “”}.
For the second sample, possible corresponding optimal values of s’ are {“axbaxxb”, “abaxxb”, “axbab”, “abab”, “aba”, “ab”, “a”, “”}.
题意:
有两个字符串S,P。现在要求从s中去除x个字符得到s‘,x的范围是0到字符串S的长度。并且去除x个字符的所有情况中s’中有几个和p相同的字符串,并且要求这些相同的字符串不能够重叠。
题解:
这道题目在读懂题目后会想到利用动态规划,我们可以利用dp【i】【k】数组来记录s的前i个长度的字符串中去除k个字符后的s’中含有p的个数。
下面是状态转移方程:

dp[i][k]=max(dp[i-1][k],dp[i-1][k-1])//应该是否去除第i个字符,前者为不去掉,后者为去掉
dp[i][k]=max(dp[i][k],dp[j][k-(i-j-l2p)]+1)//如果s‘中含有p,则通过比较大小,记录当前状态下的最大个数

语言以及注释很难描述的非常清楚,还请读者自己认真理解代码!
附上AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
char s[2005],p[2005];
int l1s,l2p,j,dp[2005][2005],f;

int check(int i)//判断S从(i-L2p)(当然i-L2p要大于零)到i之间的字符串中是否含有p
{
    int x=i,y=l2p;
    while (x && y)//判断s中(i-l2p,i)之间是否含有P
    {
        if (!y) break;
        if (s[x-1]==p[y-1]) {x--; y--;}
        else x--;
    }
    if (!y)//如果y==0则表示在此区间内含有p,返回1
    {
        j=x;//付给j减去这段p时s之前的字符长度
        return 1;
    }
    else//如果此区间内没有p则返回0
    {
        j=0;
        return 0;
    }
}

int main()
{
    scanf("%s",s);
    scanf("%s",p);
    l1s=strlen(s);
    l2p=strlen(p);
    for (int i=1;i<=l1s;i++)
    {
        f=check(i);
        for (int k=0;k<=i;k++)
        {
            dp[i][k]=max(dp[i-1][k],dp[i-1][k-1]);//是否取第i个字符
            if (f && j>=k-i+j+l2p && k-i+j+l2p>=0) dp[i][k]=max(dp[i][k],dp[j][k-(i-j-l2p)]+1);//通过比较大小来记录当前状态下的含有p的最大数量
                     //这里是为了保证 一、check的区间内含有p 二、dp【i】【j】中的i要大于j  三、dp【i】【j】中的j要大于零
        }
    }
    for (int i=0;i<=l1s;i++)
        printf("%d ",dp[l1s][i]);
    return 0;
}

欢迎评论!

猜你喜欢

转载自blog.csdn.net/wjl_zyl_1314/article/details/83511276
今日推荐