HDU4271 Find Black Hand(编辑距离,dp)

Problem Description

I like playing game with my friends, although sometimes look pretty
naive. Today I invent a new game called find black hand. The game is
not about catching bad people but playing on a string. Now I generate
a string S and several short ones s[i], and I define three kinds of
operations.
1. Delete: remove the ith character.
2. Insert: in any position, insert a character if you like.
3. Change: change the ith character into another character if you like. For each short string s[i], we define a function f(i). After
several operations on S, we can find a substring of S which is the
same to s[i]. And f(i) is the minimal number of operations to achieve.
It looks so native that I think every one of you can solve f(i)
perfectly. So I join the string S from end to end, and f(i) changes
nothing. So the string “bb” is also a substring of string “baaab”. The
“black hand” is the short string s[i] whose f(i) is minimal. Now it’s
your time to find the black hand.

Input

There are multiple test cases. The first line contains a non-empty
string S whose length is not more than 100,000. The next line contains
an integer N (1 <= N <= 10) indicating the number of the short string.
Each of the next N lines contains a short non-empty string whose
length is not more than 10. All strings in the input would not have
blank and all characters are lower case.

Output

For each test case, output a string first indicating the “black hand”,
and then output an integer indicating the minimal number of the
operation. If there are more than one “black hand”, please output the
smallest one in lexicographical order.

Sample Input

aaabbbb
2
alice
bob

Sample Output

bob 1

思路

本题前置技能:编辑距离

先说题意,题目首先给了一个模式串,然后给了若干串,每一个串的长度不超过10,题目规定,母串是一个循环串,也就是可以成为一个环,题目让你从给出的串中找出一个串,使得母串通过编辑距离之后变成这个小串,且花费最小。

这是一个编辑距离问题,因为母串是一个循环串,而给出的每个串的长度不超过10,所以我们可以把母串中的前10个字符给家加到后面去,然后判断子串的长度是否大于母串。如果子串的长度大于母串,那么就枚举母串(已经加字符后的)的每一个位置开始的串,然后用编辑距离求出母串变成子串的最小花费,刷新最小值。如果子串的长度小于母串,那么母串变成子串就可以直接利用已经增加字母的母串求出编辑距离。

因为是母串变成子串,所以在编辑距离的时候,只初始化dp[i][0],不初始化dp[0][j]

代码

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
const int N=100500+200;
char s[N];
char son[12][20];
int dp[12][N];
int get_mindis(char *son,char *s,int slen,int flen)
{
    int minn=inf;
    for(int i=0; i<=slen; i++)dp[i][0]=i;
    // for(int j=0; j<=flen; j++)dp[0][j]=j;
    for(int i=1; i<=slen; i++)
    {
        for(int j=1; j<=flen; j++)
        {
            dp[i][j]=min(min(dp[i-1][j]+1,dp[i][j-1]+1),dp[i-1][j-1]+(son[i-1]==s[j-1]?0:1));
            if(i==slen)
                minn=min(minn,dp[i][j]);
        }
    }
    return minn;
}
int main()
{
    int n;
    while(~scanf("%s",s))
    {
        mem(dp,0);
        int s_len=strlen(s);
        int ans=inf,pos=0;
        for(int i=s_len,j=0; j<=10; j++)
        {
            s[i+j]=s[j];
        }
        s[s_len+10]='\0';
        scanf("%d",&n);
        for(int i=0; i<n; i++)
        {
            int minn=inf;
            scanf("%s",son[i]);
            int son_len=strlen(son[i]);
            if(son_len>s_len)
            {
                for(int j=0; j<s_len; j++)
                    minn=min(minn,get_mindis(son[i],s+j,son_len,s_len));
            }
            else
            {
                minn=min(minn,get_mindis(son[i],s,son_len,s_len+min(10,s_len)));
            }
            if(minn<ans||(ans==minn)&&(strcmp(son[pos],son[i])>0))
            {
                ans=minn;
                pos=i;
            }
        }
        printf("%s %d\n",son[pos],ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值