题目大意:
递变(edit step)是指通过增加、减少或改变单词 x 中的一个字母,使它变成字典中的另一个单词 y。
比如将 dig 变为 dog,将 dog 变成 do 都是递变。递变阶梯(edit step ladder)是一个按字典序排列的单词序列 w1,w2,... ,wn,满足对于从 1 到 n - 1 的所有 i,单词 wi 到 w(i+1)都是一次递变。
现在给出一部字典,你要计算其中最长的递变阶梯。
递变(edit step)是指通过增加、减少或改变单词 x 中的一个字母,使它变成字典中的另一个单词 y。
比如将 dig 变为 dog,将 dog 变成 do 都是递变。递变阶梯(edit step ladder)是一个按字典序排列的单词序列 w1,w2,... ,wn,满足对于从 1 到 n - 1 的所有 i,单词 wi 到 w(i+1)都是一次递变。
现在给出一部字典,你要计算其中最长的递变阶梯。
解析:这题我是用普通的O(n^2),的最长上升子序列求解,2739ms,时间有些久。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 25005;
int dp[N];
char str[N][18];
int len[N];
int n;
inline bool equal(char s1[], char s2[]) {
int cnt = 0;
for(int i = 0; s1[i]; i++)
if(s1[i] != s2[i])
cnt++;
if(cnt == 1)
return true;
return false;
}
inline bool more(char s1[],char s2[]) {
int cnt = 0;
for(int i = 0,j = 0; s1[i]; i++) {
if(s1[i] == s2[j])
j++;
else
cnt++;
}
if(cnt == 1)
return true;
return false;
}
inline bool judge(int a,int b) { //判断两个字符串是否是一个edit
if(len[a] == len[b] && equal(str[a],str[b]))
return true;
else if(len[a] - len[b] == 1 && more(str[a],str[b]))
return true;
else if(len[b] - len[a] == 1 && more(str[b],str[a]))
return true;
return false;
}
int main() {
n = 0;
while(scanf("%s",str[n]) != EOF) {
len[n] = strlen(str[n]);
n++;
}
int ans = 0;
for(int i = 0; i < n; i++) {
dp[i] = 1;
for(int j = 0; j < i; j++) {
if(judge(i,j) && dp[i] < dp[j] + 1) {
dp[i] = dp[j] + 1;
}
}
if(dp[i] > ans) {
ans = dp[i];
}
}
printf("%d\n",ans);
return 0;
}