这么水的一道最短编辑距离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 }