10029 - Edit Step Ladders

来源:互联网 发布:网络舆情监测员工资 编辑:程序博客网 时间:2024/05/29 16:05

这道题目题意很清晰,也很容易想到一个O(n2)的算法,但是n有25000, O(n2)算法会超时。

我的同学曾跟我说过O(n*logn*2*26*16)的算法,之前一直没做,今天在多次WA之后,终于AC了。

我们这样考虑:一个单词(假设长度为16)由其他的单词经过删除,添加,替换一个字母得到,反过来,我们可以由这个单词经过相反的操作得到其他单词,效果是的等价的。设f[i]表示以第i个单词结尾的最长的编辑距离,则我们对第i个单词做16(单词的长度)次删除操作,16*26次添加操作,16*26次替换操作,从第0个到第i-1个单词中二分查找匹配的单词,若匹配,则更新,这样复杂度就降下来了。但效率还是不太高。

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int MAXN = 25010;char s[MAXN][20];int f[MAXN];int binary(int l, int r, char *_s){    int m, t;    while(l < r){        m = l + (r - l) / 2;        if(!(t = strcmp(_s, s[m]))){            return m;        }else if(t > 0){            l = m + 1;        }else r = m;    }    if(!strcmp(_s, s[m]))        return m;    return -1;}int main(){    //freopen("input.txt", "r", stdin);    int n = 0, len, ans;    char t[20];    while(scanf("%s", s[n]) == 1) n++;    int p;    memset(f, 0, sizeof(f));    ans = f[0] = 1;    for(int i = 1; i < n; i++){        f[i] = 1;        len = strlen(s[i]);        for(int k = len - 1; k >= 0; k--){  //删除            strcpy(t, s[i]);            for(int j = k; j < len; j++)                t[j] = t[j + 1];            p = binary(0, i, t);            if(p != -1 && f[i] < f[p] + 1)                f[i] = f[p] + 1;        }        for(int k = len; k >= 0; k--){//添加            strcpy(t, s[i]);            for(int j = len; j >= k; j--){                t[j + 1] = t[j];            }            int up;            if(k == len) up = 25;            else up = s[i][k] - 'a';            for(int j = 0; j <= up; j++){                t[k] = j + 'a';                p = binary(0, i, t);                if(p != -1 && f[i] < f[p] + 1)                    f[i] = f[p] + 1;            }        }        for(int k = len - 1; k >= 0; k--){ //替换            strcpy(t, s[i]);            for(int j = 0; j < s[i][k] - 'a'; j++){                t[k] = j + 'a';                p = binary(0, i, t);                if(p != -1 && f[i] < f[p] + 1)                    f[i] = f[p] + 1;            }        }        if(ans < f[i]) ans = f[i];    }    printf("%d\n", ans);    return 0;}