UVA 10029 Edit Step Ladders

UVA_10029

    这个题目一开始想转化成最长上升子序列的模型,但发现这样不好做,后来看了别人的题解发现可以转化成找有向无环图的最长路去做。

    这样面临的一个问题就是如果显性地建图的话是没办法存下每条边的,于是我们不妨在每次尝试连线的时候再判断这条边是否存在。

    为了方便判断两个字符串之间是否有一条有向边,我们不妨以起点为基础,施加3种变换,观察是否可以变换出字典里的字符串,如果可以变换出的话,就说明这两个字符串之间存在一条有向边。

    对于判断是否可以变换出字典里的字符串这一步,可以用哈希表也可以二分查找字典。找最长路的过程可以采用记忆化搜索的方式。

#include<stdio.h>
#include<string.h>
#define MAXD 25010
#define HASH 1000003
int N, head[HASH], next[MAXD], f[MAXD];
char b[MAXD][20], temp[20];
int hash(char *str)
{
int v = 0, seed = 131;
while(*str)
v = v * seed + *(str ++);
return (v & 0x7fffffff) % HASH;
}
void insert(int s)
{
int i, h;
h = hash(b[s]);
next[s] = head[h];
head[h] = s;
}
int search()
{
int i, h;
h = hash(temp);
for(i = head[h]; i != -1; i = next[i])
if(strcmp(b[i], temp) == 0)
break;
return i;
}
void init()
{
N = 0;
memset(head, -1, sizeof(head));
while(scanf("%s", b[N]) == 1)
{
insert(N);
N ++;
}
}
void add(int s, int st, int k)
{
int i, j;
for(i = 0, j = 0; i < st; i ++, j ++)
temp[j] = b[s][i];
temp[j ++] = 'a' + k;
for(; b[s][i]; i ++, j ++)
temp[j] = b[s][i];
temp[j] = '\0';
}
void del(int s, int st)
{
int i, j;
for(i = 0, j = 0; i < st; i ++, j ++)
temp[j] = b[s][i];
i ++;
for(; b[s][i]; i ++, j ++)
temp[j] = b[s][i];
temp[j] = '\0';
}
void change(int s, int st, int k)
{
strcpy(temp, b[s]);
temp[st] = 'a' + k;
}
int dp(int cur)
{
int i, j, k, st, len, s, t, max;
if(f[cur] != -1)
return f[cur];
max = 0;
len = strlen(b[cur]);
for(st = 0; st <= len; st ++)
for(k = 0; k < 26; k ++)
{
add(cur, st, k);
s = search();
if(s != -1 && strcmp(b[cur], temp) < 0)
{
t = dp(s);
if(t + 1 > max)
max = t + 1;
}
}
for(st = 0; st < len; st ++)
{
del(cur, st);
s = search();
if(s != -1 && strcmp(b[cur], temp) < 0)
{
t = dp(s);
if(t + 1 > max)
max = t + 1;
}
}
for(st = 0; st < len; st ++)
for(k = 0; k < 26; k ++)
{
change(cur, st, k);
s = search();
if(s != -1 && strcmp(b[cur], temp) < 0)
{
t = dp(s);
if(t + 1 > max)
max = t + 1;
}
}
return f[cur] = max;
}
void solve()
{
int i, t, max = 0;
memset(f, -1, sizeof(f));
for(i = 0; i < N; i ++)
{
t = dp(i);
if(t > max)
max = t;
}
printf("%d\n", max + 1);
}
int main()
{
init();
solve();
return 0;
}


原文地址:https://www.cnblogs.com/staginner/p/2269222.html