HDU 4271 Find Black Hand [最短编辑距离DP]

  这么水的一道最短编辑距离DP,比赛的时候居然没有去做。。

  很裸的最短编辑距离DP,就是要注意环的问题。因为如果直接copy两遍的话,有可能会将本来是同一个位置的字母使用两次。但是可以发现串的长度只有10,最大的编辑距离不会超过10,当原串长度>2*L时环就没有影响了,因为这时如果环中一个字母被使用两次,那最短编辑距离肯定已经大于L了。

  我是长度小于20时暴力枚举,大于30时在原串后面copy原创的前20个字符。

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #define INF 0x3fffffff
 5 #define MAXN 100105
 6 int n,l1,l2,ans,tmp;
 7 char s1[MAXN],s2[12][12],ansid;
 8 int d[12][MAXN];
 9 inline int min(const int &x,const int &y){return x<y?x:y;}
10 int dp(char *s1,char *s2,int l1,int l2){
11     int ret=INF;
12     for(int i=1;i<=l1;i++){
13         d[i][0]=i;
14         for(int j=1;j<=l2;j++){
15             d[i][j]=min(d[i-1][j-1]+(s1[i-1]!=s2[j-1]),min(d[i-1][j],d[i][j-1])+1);
16             if(i==l1)ret=min(ret,d[i][j]);
17         }
18     }
19     return ret;
20 }
21 int main(){
22     //freopen("test.in","r",stdin);
23     while(scanf("%s",s1)!=EOF){
24         l1=strlen(s1);
25         scanf("%d",&n);
26         ans=INF,ansid=-1;
27         for(int i=0;i<n;i++){
28             scanf("%s",s2[i]);
29             l2=strlen(s2[i]);
30             tmp=INF;
31             if(l1<20){
32                 for(int j=0;j<l1;j++){
33                     tmp=std::min(tmp,dp(s2[i],s1+j,l2,l1));
34                     s1[l1+j]=s1[j];
35                 }
36             }else{
37                 for(int j=0;j<20;j++)s1[l1++]=s1[j];
38                 tmp=dp(s2[i],s1,l2,l1);
39             }
40             if(tmp<ans||tmp==ans&&strcmp(s2[i],s2[ansid])<0){
41                 ansid=i,ans=tmp;
42             }
43         }
44         printf("%s %d\n",s2[ansid],ans);
45     }
46     return 0;
47 }
posted @ 2012-09-10 22:25 Burn_E 阅读(...) 评论(...) 编辑 收藏