uva10029 - Edit Step Ladders(巧妙动归)

由于这个题目的数据量较大,所以枚举比较的动归求解方法就不大行了,,,

此时我们就从当前字符串出发,

主动变换成符合题意的未知串,

然后在所有字典序小于当前串的字符串中寻找未知串是否出现过。

这样就复杂度就从O(n^2)降到了O(nlog(n));

其实两种方法的动归方程都是一样的,就是比较的方式不同,,

第二种方法优化了字符串比较。。。。

状态:dp[i]表示前i个单词所能形成的递变阶梯最大值。。。

状态转移:dp[i] = dp[x]+1;(s[i]与s[x]满足题目中的变化关系)

 

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 25005
#define N 20
char str[M][N], s[N];
int ans, n, dp[M];
void Add(int x, int y, int c)
{
    memset(s,0,sizeof(s));
    for(int i = 0; i < y; i++) s[i] = str[x][i];
    s[y] = 'a'+c;
    for(int i = y; str[x][i]; i++) s[i+1] = str[x][i];
}
void Change(int x, int y, int c)
{
    memset(s,0,sizeof(s));
    for(int i = 0; i < y; i++) s[i] = str[x][i];
    s[y] = 'a'+c;
    for(int i = y+1; str[x][i]; i++) s[i] = str[x][i];
}
void Delete(int x, int y)
{
    memset(s,0,sizeof(s));
    for(int i = 0; i < y; i++) s[i] = str[x][i];
    for(int i = y+1; str[x][i]; i++) s[i-1] = str[x][i];
}
int search(int l, int r)
{
    int mid;
    while(l<=r)
    {
        mid = (r+l)/2;
        if(!strcmp(str[mid],s)) return mid;
        else if(strcmp(str[mid],s)>0) r = mid-1;
        else l = mid+1;
    }
    return 0;
}
int main ()
{
    n = 0;
    ans = 0;
    dp[1] = 1;
    while(~scanf("%s",str[++n]));
    n-=1;
    for(int i = 2; i <= n; i++)
    {
        dp[i] = 1;
        for(int j = 0; str[i][j]; j++)
        {
            Delete(i,j);
            int cur;
            if(cur = search(1,i)) dp[i] = max(dp[i],dp[cur]+1);
            for(int k = 0; 'a'+k<str[i][j]; k++)
            {
                Add(i,j,k);
                if(cur = search(1,i)) dp[i] = max(dp[i],dp[cur]+1);
                Change(i,j,k);
                if(cur = search(1,i)) dp[i] = max(dp[i],dp[cur]+1);
            }
        }
        ans = max(ans,dp[i]);
    }
    printf("%d\n",ans);
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值