For a given dictionary, you are to compute the length of the longest edit step ladder.
cat dig dog fig fin fine fog log wine
5题意:给定一个字典,如果经过删除,添加或替换能转换成另一个单词,则这两个单词为阶梯变化,求出最长阶梯变化的字典。
思路:dp。lis,用n^2 超时了。。。然后没想明白看题解,发现有n(logn)方法。
把每个单词可以变换的情况全部弄出来,然后在前面进行2分查找,由于序列本身是字典序所以可行。这样就能过了
代码:
#include <stdio.h> #include <string.h> int max(int a, int b) {return a > b ? a : b;} int min(int a, int b) {return a < b ? a : b;} const int N = 25555, M = 20; char word[N][M], str[M]; int n, i, j, k, l, dp[25555], ans; void change(char *word, char *str, char c, int wei) { int i; for (i = 0; word[i]; i ++) str[i] = word[i]; str[wei] = c; str[i] = '\0'; } void del(char *word, char *str, int wei) { int i; for (i = 0; i < wei; i ++) str[i] = word[i]; for (i = wei + 1; word[i]; i ++) str[i - 1] = word[i]; str[i - 1] = '\0'; } void add(char *word, char *str, char c, int wei) { int i; for (i = 0; i < wei; i ++) str[i] = word[i]; str[wei] = c; for (i = wei; word[i]; i ++) str[i + 1] = word[i]; str[i + 1] = '\0'; } void tra(char *word, char *str, char c, int wei, int flag) { if (flag == 0) change(word, str, c, wei); else if (flag == 1) del(word, str, wei); else add(word, str, c, wei); } int find(char *str, int j) { int i = 0; j --; while (i <= j) { int mid = (i + j) / 2; if (strcmp(word[mid], str) == 0) { return mid; } else if (strcmp(word[mid], str) < 0) { i = mid + 1; } else j = mid - 1; } return -1; } int main() { while (gets(word[n])) { n ++; } ans = 0; for (i = 0; i < n; i ++) { dp[i] = 1; for (k = 0; k < 3; k ++) { for (j = 0; word[i][j]; j ++) { for (l = 0; l < 26; l ++) { tra(word[i], str, 'a' + l, j, k); if (strcmp(word[i], str) < 0) break; int mid = find(str, i); if (mid >= 0) dp[i] = max(dp[i], dp[mid] + 1); } } } ans = max(ans, dp[i]); } printf("%d\n", ans); return 0; }