[简单DP] HDOJ 4323 Magic Number

// 编辑距离的方法可以水过这道题

编辑距离的计算方法即一个不完全的证明见:http://en.wikipedia.org/wiki/Levenshtein_distance

具体如下图:

\qquad\operatorname{lev}_{a,b}(i,j) = \begin{cases}
  0 &, i=j=0 \\
  i &, j = 0 \land i > 0 \\
  j &, i = 0 \land j > 0 \\
  \min \begin{cases}
          \operatorname{lev}_{a,b}(i-1,j) + 1 \\
          \operatorname{lev}_{a,b}(j,i-1) + 1 \\
          \operatorname{lev}_{a,b}(i-1,j-1) + [a_i \neq b_j]
       \end{cases} &, \text{ else}
\end{cases}

# include <cstdio>
# include <cstring>

# define LEN 10 + 2
# define N 1500 + 5

int n, m;
char s[LEN];
int len[N];
char dic[N][LEN];

int Abs(int x)
{
    return x>0 ? x:-x;
}

int Min(int x, int y, int z)
{
    int t = x<y ? x:y;
    return t<z ? t:z;
}

int levenshtein(char* s, char* t, int n, int m)
{
    int i, j, d[LEN][LEN];            
    for (i = 0; i <= n; ++i)
        d[i][0] = i;
    for (i = 0; i <= m; ++i)
        d[0][i] = i;
    for (i = 1; i <= n; ++i)
    for (j = 1; j <= m; ++j)
    {
        if (s[i-1]==t[j-1])
            d[i][j] = d[i-1][j-1];
        else
            d[i][j] = Min(d[i-1][j], d[i][j-1], d[i-1][j-1])+1;
    }
    return d[n][m];
}

void solve(void)
{
    int i, j, th, lens, cnt;
    scanf("%d%d", &n, &m);
    for (i = 0; i < n; ++i)
    {
        scanf("%s", dic[i]);
        len[i] = strlen(dic[i]);
    }
    for (i = 0; i < m; ++i)
    {
        cnt = 0;
        scanf("%s%d", s, &th);
        lens = strlen(s);
        for (j = 0; j < n; ++j)
        {
            if (Abs(lens-len[j]) > th) continue;
            if (levenshtein(s, dic[j], lens, len[j]) <= th)
                ++cnt;
        }
        printf("%d\n", cnt);
    }
}

int main()
{
    int T;
    
    scanf("%d", &T);
    for (int i = 0; i < T; ++i)
    {
        printf("Case #%d:\n", i+1);
        solve();
    }
    
    return 0;
}

最优性证明可能比较复杂。

posted on 2012-08-05 22:12  getgoing  阅读(237)  评论(0编辑  收藏  举报

导航