2013-05-04 14:24:43Morris
[UVA][dp] 10029 - Edit Step Ladders
Problem C: Edit Step Ladders
An edit step is a transformation from one word x to another word y such that x and y are words in the dictionary, and x can be transformed to y by adding, deleting, or changing one letter. So the transformation from dig to dog or from dog to do are both edit steps. An edit step ladder is a lexicographically ordered sequence of words w1, w2, ... wn such that the transformation from wi to wi+1 is an edit step for all i from 1 to n-1.
For a given dictionary, you are to compute the length of the longest edit step ladder.
Input
The input to your program consists of the dictionary - a set of lower case words in lexicographic order - one per line. No word exceeds 16 letters and there are no more than 25000 words in the dictionary.Output
The output consists of a single integer, the number of words in the longest edit step ladder.Sample Input
cat dig dog fig fin fine fog log wine
Sample Output
5
雖然這題是要求挑一個最長字典順序,而相鄰兩個單字可以藉由增加,刪除,修改達到。
不可能一個一個去比較,因此要窮舉可以修改成什麼,然後去做查找。
// 使用 map
#include <stdio.h>
#include <string.h>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
int dp[25005];
map<string, int> R[50];
//adding, deleting, or changing one letter
int main() {
char word[16];
int n = 0;
int i, j, ret = 0;
while(gets(word)) {
int len = strlen(word);
int mx = 0;
string x = word;
string y;
map<string, int>::iterator it;
for(i = 0; i <= len; i++) {//adding
for(j = 'a'; j <= 'z'; j++) {
y = x.substr(0, i) + (char)j + x.substr(i);
it = R[y.length()].find(y);
if(it != R[y.length()].end())
mx = max(mx, dp[it->second]);
if(y.compare(x) > 0)
break;
//cout << y << y.compare(x) << endl;
}
}
for(i = 0; i < len; i++) {//deleting
y = x.substr(0, i) + x.substr(i+1);
it = R[y.length()].find(y);
if(it != R[y.length()].end())
mx = max(mx, dp[it->second]);
//cout << y << endl;
}
y = x;
for(i = 0; i < len; i++) {//changing
for(j = 'a'; j <= 'z'; j++) {
char o = y[i];
y[i] = j;
it = R[y.length()].find(y);
if(it != R[y.length()].end())
mx = max(mx, dp[it->second]);
//cout << y << endl;
y[i] = o;
if(y.compare(x) > 0)
break;
}
}
dp[n] = mx+1;
ret = max(ret, dp[n]);
R[x.length()][x] = n;
n++;
}
printf("%d\n", ret);
return 0;
}
// 使用 hash function + map 速度更快
#include <stdio.h>
#include <string.h>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
int dp[25005];
map<string, int> R[10007];
//adding, deleting, or changing one letter
unsigned int fnv_hash (const void* key, int len) {
unsigned char* p = (unsigned char *)key;
unsigned int h = 2166136261UL;
int i;
for (i = 0; i < len; i++)
h = (h*16777619) ^ p[i];
return h;
}
int main() {
char word[16];
int n = 0;
int i, j, ret = 0;
while(gets(word)) {
int len = strlen(word);
int mx = 0;
string x = word;
string y;
map<string, int>::iterator it;
unsigned int h;
for(i = 0; i <= len; i++) {//adding
for(j = 'a'; j <= 'z'; j++) {
y = x.substr(0, i) + (char)j + x.substr(i);
h = fnv_hash(y.c_str(), y.length())%10007;
it = R[h].find(y);
if(it != R[h].end())
mx = max(mx, dp[it->second]);
if(y.compare(x) > 0)
break;
//cout << y << y.compare(x) << endl;
}
}
for(i = 0; i < len; i++) {//deleting
y = x.substr(0, i) + x.substr(i+1);
h = fnv_hash(y.c_str(), y.length())%10007;
it = R[h].find(y);
if(it != R[h].end())
mx = max(mx, dp[it->second]);
//cout << y << endl;
}
y = x;
for(i = 0; i < len; i++) {//changing
for(j = 'a'; j <= 'z'; j++) {
char o = y[i];
y[i] = j;
h = fnv_hash(y.c_str(), y.length())%10007;
it = R[h].find(y);
if(it != R[h].end())
mx = max(mx, dp[it->second]);
//cout << y << endl;
y[i] = o;
if(y.compare(x) > 0)
break;
}
}
dp[n] = mx+1;
ret = max(ret, dp[n]);
h = fnv_hash(x.c_str(), x.length())%10007;
R[h][x] = n;
n++;
}
printf("%d\n", ret);
return 0;
}
// 使用 Trie, 速度最快的一個
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
struct Node {
Node *next[26];
int label;
Node() {
label = -1;
memset(next, 0, sizeof(next));
}
};
void insertTrie(const char *str, Node *root, int label) {
static Node *p;
static int i, idx;
p = root;
for(i = 0; str[i]; i++) {
idx = str[i]-'a';
if(p->next[idx] == NULL)
p->next[idx] = new Node();
p = p->next[idx];
}
p->label = label;
}
int findTrie(const char *str, Node *root) {
static Node *p;
static int i, idx;
p = root;
for(i = 0; str[i]; i++) {
idx = str[i]-'a';
p = p->next[idx];
if(p == NULL) return -1;
}
return p->label;
}
int dp[25005];
//adding, deleting, or changing one letter
int main() {
char word[16];
int n = 0;
Node *root = new Node();
int i, j, ret = 0;
while(gets(word)) {
int len = strlen(word);
int mx = 0;
int findret = -1;
string x = word;
string y;
for(i = 0; i <= len; i++) {//adding
for(j = 'a'; j <= 'z'; j++) {
y = x.substr(0, i) + (char)j + x.substr(i);
findret = findTrie(y.c_str(), root);
if(findret >= 0)
mx = max(mx, dp[findret]);
if(y.compare(x) > 0)
break;
//cout << y << y.compare(x) << endl;
}
}
for(i = 0; i < len; i++) {//deleting
y = x.substr(0, i) + x.substr(i+1);
findret = findTrie(y.c_str(), root);
if(findret >= 0)
mx = max(mx, dp[findret]);
//cout << y << endl;
}
y = x;
for(i = 0; i < len; i++) {//changing
for(j = 'a'; j <= 'z'; j++) {
char o = y[i];
y[i] = j;
findret = findTrie(y.c_str(), root);
if(findret >= 0)
mx = max(mx, dp[findret]);
//cout << y << endl;
y[i] = o;
if(y.compare(x) > 0)
break;
}
}
dp[n] = mx+1;
ret = max(ret, dp[n]);
insertTrie(x.c_str(), root, n);
n++;
}
printf("%d\n", ret);
return 0;
}