做题感悟:开始做这题时每次向前寻找最优时就用LCS判断一下是否可以转化,结果超时,最后看了一下才知道原来这样。
解题思路:
判断当前字符串时,枚举每一种情况,包括添加,删除,改写一个字符,然后就是关键之处了,寻找的时候用二分查找,有的人可能不解,这样怎么用二分呢 ? 你太低估二分的实力了,因为给的字符串是有序的可以用字符串比较函数比较,这样就可以二分了。
代码:
#include<iostream>
#include<iomanip>
#include<string.h>
#include<string>
#include<stdio.h>
#include<stdlib.h>
using namespace std ;
const int MY = 20 ;
const int MX = 25000 + 10 ;
int n ;
int dp[MX] ;
char s[MX][MY],str[MY] ;
void change(char *s1,char *s2,int x,char ch)// 改变对应位置字符
{
int p=0 ;
for(int i=0 ;s1[i] ;i++)
if(i==x)
s2[p++]=ch ;
else s2[p++]=s1[i] ;
s2[p++]='\0' ;
}
void add(char *s1,char *s2,int x,char ch) // 添加字符
{
int len=strlen(s1),p=0 ;
for(int i=0 ;i<x ;i++)
s2[p++]=s1[i] ;
s2[p++]=ch ;
for(int i=x ;i<len ;i++)
s2[p++]=s1[i] ;
s2[p++]='\0' ;
}
void del(char *s1,char *s2,int x) // 删除对应字符
{
int p=0 ;
for(int i=0 ;s1[i] ;i++)
if(i!=x)
s2[p++]=s1[i] ;
s2[p++]='\0' ;
}
void tran(char *s1,char *s2,int i,int flag,char ch)
{
if(!flag) change(s1,s2,i,ch) ;
else if(flag==1) add(s1,s2,i,ch) ;
else del(s1,s2,i) ;
}
int binary_search(int le,int rt,char *str) // 二分
{
int mid ;
while(le<rt)
{
mid=(le+rt)/2 ;
if(!strcmp(s[mid],str)) return mid ;
else strcmp(s[mid],str)>0 ? rt=mid : le=mid+1 ;
}
return -1 ;
}
void work()
{
int ans=0 ;
memset(dp,0,sizeof(dp)) ;
for(int i=0 ;i<n ;i++)
{
dp[i]=1 ;
int len=strlen(s[i]) ;
for(int t=0 ;t<3 ;t++) // 枚举每一种情况
{
for(int j=0 ;j<=len ;j++)
{
if(j==len&&t!=1) continue ;
for(int k=0 ;k<26 ;k++)
{
tran(s[i],str,j,t,k+'a') ;
if(strcmp(s[i],str)<0) break ;
int mx=binary_search(0,i,str) ;
if(mx!=-1)
dp[i]=max(dp[i],dp[mx]+1) ;
}
}
}
ans = max(ans,dp[i]) ;
}
cout<<ans<<endl ;
}
int main()
{
n=0 ;
while(cin>>s[n++]) ;
n-- ;
work() ;
return 0 ;
}