您的位置:首页 > 其它

UVa 10029 Edit Step Ladders(hash状态压缩DP)

2012-11-21 15:45 357 查看
题意:

给定多个字符串,是按照字典顺序排列的。一个字符串如果能够可以通过改变一个字母,删除一个字母,增加一个字母变成后面的某一个字符串,

那么称这两个字符串之间存在一个阶梯,问最多有多少个阶梯。

思路:

/article/4928143.html

这一题的难点在于题目数据量很大,O(n^2)的算法铁定会超时。另类的解题思路是:构造一个hash表,把给定的字符串都存进去。

然后试图对每个字符串进行删除,插入,修改等操作,查询经过变换后的字符串是否在hash表中,并且这个变换后的字符串要在源字符串的后面。

然后记忆化搜索得出最长的阶梯。

#include <cstdio>
#include <cstdlib>
#include <cstring>

const int MAXN = 25010;
const int HASH = 1000010;
int n, head[HASH], next[MAXN], f[MAXN];
char b[MAXN][20], temp[20];

int hash(const char *s)
{
int v = 0, seed = 131;
while (*s)
v = v * seed + *(s++);
return (v & 0x7fffffff) % HASH;
}

void insert(int s)
{
int h = hash(b[s]);
next[s] = head[h];
head[h] = s;
}

int search(const char *s)
{
int i, h = hash(s);
for (i = head[h]; i != -1; i = next[i])
if (!strcmp(b[i], s))
break;
return i;
}

void add(const char *s, int p, int d)
{
int i = 0, j = 0;

while (i < p)
temp[j++] = s[i++];

temp[j++] = 'a' + d;

while (s[i])
temp[j++] = s[i++];

temp[j] = '\0';
}

void del(const char *s, int p)
{
int i = 0, j = 0;

while (i < p)
temp[j++] = s[i++];

++i;

while (s[i])
temp[j++] = s[i++];

temp[j] = '\0';
}

void change(const char *s, int p, int d)
{
strcpy(temp, s);
temp[p] = 'a' + d;
}

int dp(int s)
{
if (f[s] != -1)
return f[s];

int ans = 0;
int len = strlen(b[s]);

for (int p = 0; p <= len; ++p)
{
for (int d = 0; d < 26; ++d)
{
add(b[s], p, d);
int v = search(temp);
if (v != -1 && strcmp(b[s], temp) < 0)
{
int t = dp(v);
if (ans < t + 1)
ans = t + 1;
}
}
}

for (int p = 0; p < len; ++p)
{
del(b[s], p);
int v = search(temp);
if (v != -1 && strcmp(b[s], temp) < 0)
{
int t = dp(v);
if (ans < t + 1)
ans = t + 1;
}
}

for (int p = 0; p < len; ++p)
{
for (int d = 0; d < 26; ++d)
{
change(b[s], p, d);
int v = search(temp);
if (v != -1 && strcmp(b[s], temp) < 0)
{
int t = dp(v);
if (ans < t + 1)
ans = t + 1;
}
}
}
return f[s] = ans;
}

void solve()
{
memset(f, -1, sizeof(f));
int ans = 0;
for (int i = 0; i < n; ++i)
{
int t = dp(i);
if (ans < t)
ans = t;
}
printf("%d\n", ans + 1);
}

void init()
{
n = 0;
memset(head, -1, sizeof(head));

while (scanf("%s", b
) == 1)
{
insert(n), ++n;
}
}

int main()
{
init();
solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: