是一个最长上升子序列类似的问题,但是如果我们直接去跑,是会超时的,因为在得到一个状态的最大值的时候,我们都要判断近乎25000个单词,但实际上,并没有那么多个单词会与当前单词存在一个阶梯,所以我们通过当前这个单词能变成成什么单词,来找出相应的单词是否在给定的字符串集合中,可以降低寻找的范围。。。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int N=26000; char str[N][20]; int dp[N]; void dele(char*,char*,int); void add(char*,char*,int,char); void repla(char*,char*,int,char); int ifind(int,int,char*); void fun(char*,int); int main() { int n=0,imax=0; while(scanf("%s",str[n])!=EOF) n++; memset(dp,0,sizeof(dp)); for(int i=1;i<n;i++) { int len=strlen(str[i]); for(int j=0;j<=len;j++) { char temp[20]={0}; for(char k='a';k<='z';(int)k++) { if(j<len) { repla(str[i],temp,j,k); fun(temp,i); } add(str[i],temp,j,k); fun(temp,i); } if(j<len) { dele(str[i],temp,j); fun(temp,i); } } imax=max(imax,dp[i]); } printf("%d\n",imax+1); } void dele(char *str,char *res,int pos) { int len=strlen(str),cnt=0; for(int i=0;i<len;i++) { if(i!=pos) res[cnt++]=str[i]; } res[cnt]='\0'; } void repla(char *str,char *res,int pos,char letter) { int len=strlen(str); for(int i=0;i<len;i++) { if(i==pos) res[i]=letter; else res[i]=str[i]; } res[len]='\0'; } void add(char *str,char *res,int pos,char letter) { int len=strlen(str),cnt=0; for(int i=0;i<=len;i++) { if(i==pos) res[cnt++]=letter; if(i<len) res[cnt++]=str[i]; } str[cnt]='\0'; } int ifind(int be,int end,char *a) { while(be<=end) { int mid=be+(end-be)/2; int res=strcmp(str[mid],a); if(res>0) end=mid-1; else if(res==0) return mid; else be=mid+1; } return -1; } void fun(char *a,int pos) { int pre=ifind(0,pos-1,a); if(pre!=-1) dp[pos]=max(dp[pos],dp[pre]+1); }