题意:给定一个起始单词,该单词长度为3,再给定一个字典。求从起始单词开始,每步在单词上添加一个字母并且仍然出现在字典中,这样能够达到的最长的那个单词(解保证这样的单词唯一)
思路:先将词典按照单词的长度排序。思路就是对于每个单词s,扫描比它长度小1的并且可以由初始单词到达的那些单词t,如果发现s可以由t添加一个字符组成,那么s能够由初始字符到达。
判断s是否能够由t构成一开始用的lcs,后来发现用O(串长)的方法即可。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
#define INF 0x3fffffff
#define clr(s,t) memset(s,t,sizeof(s))
#define N 1005
struct node{
char s[83];
int len,flag;
}p[N];
int dp[83][83];
char t[83];
int n;
int cmp(node a,node b){
return a.len < b.len;
}
int lcs(int a,int b){
int i,j;
clr(dp, 0);
for(i = 1;i<=p[a].len;i++)
for(j = 1;j<=p[b].len;j++){
if(p[a].s[i-1] == p[b].s[j-1])
dp[i][j] = dp[i-1][j-1]+1;
else
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
return dp[i-1][j-1];
}
int main(){
int i,j,k,flag,a,b;
char res[83];
scanf("%d %s",&n,t);
strcpy(res, t);
for(i = 0;i<n;i++){
scanf("%s",p[i].s);
p[i].flag = 0;
p[i].len = (int)strlen(p[i].s);
if(!strcmp(t, p[i].s))
p[i].flag = 1;
}
sort(p,p+n,cmp);
for(i = 0;;i++)
if(p[i].len == 4)
break;
a = 0;
b = i-1;
while(i<n){
for(j = i,flag = 0;j<n&&p[j].len==p[i].len;j++)
for(k = a;k<=b;k++)
if(p[k].flag == 1 && lcs(j,k)==p[j].len-1){
p[j].flag = 1;
strcpy(res, p[j].s);
flag = 1;
break;
}
if(!flag)
break;
a = i;
b = j-1;
i = j;
}
printf("%s\n",res);
return 0;
}
int lcs(int a,int b){//a是否能够通过增加一个字符构成字符串b
int i,j;
for(i = j = 0;j<p[b].len && i<p[a].len;i++,j++)
if(p[a].s[i] != p[b].s[j])
i--;
return i==p[a].len && (j==p[b].len||j==p[a].len);
}