UVA10029 - Edit Step Ladders(LIS)

题目大意:UVA10029 - Edit Step Ladders(LIS)

题目大意:给你一个按照字典序读入的单词,然后要求你找出最长的序列,要求这个最长的序列也要满足字典序,并且后一个是由前一个单词,由在任意的地方替换,增加,删除一个字符变换来的。

解题思路:LIS。但是这里的O(n^2) 25000,超时。但是查找符合的单词有个规律,符合变换要求的单词的长度是有要求的,必须相差小于等于1.并且数据中相同长度的单词不会超过45个,那么就可以把这些单词按照长度分类,那么查找的时候就是45 * 3.省下很多的时间。然后就是单词变换,这里分替换,和删除(插入是一样的)。这种做法是因为数据的原因,正解应该是将每个单词的变换的可能都变换出来(可以预处理+hash),然后再用二分查询找到是否有对应的单词。少了return,wa了无数次。真的要细心。

代码:

#include <cstdio>
#include <cstring>

const int maxn = 25005;
const int maxnL = 20;

char word[maxn][maxnL];
int n;
int l[maxn];//单词的长度
int dp[maxn];
int kind[maxnL][maxn]; //长度分类
int c[maxnL];

int Max (const int a, const int b) { return a > b? a: b; }

bool j_del (int a, int b) {//处理增加很删除

	int flag = 0;
	for (int i = 0, j = 0; i < l[b]; i++) {

		if (word[b][i] != word[a][j]) {

			if (flag)
				return false;
			else
				flag = 1;
			continue;
		}
		j++;
	}
	if (flag)
		return true;
	return false;
}

bool judge (int a, int b) {

	if (l[a] == l[b]) {//处理替换

		int flag = 0;
		for (int i = 0; i < l[a]; i++) {
			if (word[a][i] != word[b][i]) {
				if (flag)
					return false;
				else
					flag = 1;
			}
		}
		if (flag)
			return true;
		return false;

	} else if (l[a] == l[b] + 1)
		return j_del(b, a);
	else if (l[b] == l[a] + 1)
		return j_del(a, b);
	else
		return false;
}

void search (int len, int i) {	

	for(int j = 0; j < c[len]; j++)
		if(i > kind[len][j] && judge (kind[len][j], i)) {
			dp[i] = Max (dp[i], dp[kind[len][j]] + 1);
		}
}

void handle () {

	for (int i = 1; i < n; i++) {

		search (l[i] - 1, i);
		search (l[i], i);
		search (l[i] + 1, i);
/*		for (int j = 1; j < i; j++)
			if (judge(j, i))
				dp[i] = Max (dp[i], dp[j] + 1);*/
	}
}

int main () {

	n = 1;
	memset (c, 0, sizeof (c));
	while (gets(word[n]) != NULL) {
		l[n] = strlen (word[n]);
		kind[l[n]][c[l[n]]++] = n;
		n++;
	}

	for (int i = 1; i < n; i++)
		dp[i] = 1;

	handle ();

	int ans = 0;
	for (int i = 1; i < n; i++)
		ans = Max (ans, dp[i]);

	printf ("%d\n", ans);
	return 0;
}
时间: 2024-10-01 06:16:11

UVA10029 - Edit Step Ladders(LIS)的相关文章

UVA - 10029 Edit Step Ladders (二分+hash)

Description 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 transformatio

UVA 10029 Edit Step Ladders ——(DAG求最长路)

题意:升序的给出一本若干个单词,每个单词都可删除一个字母,添加一个字母或者改变一个字母,如果任意一个操作以后能变成另外一个字典中的单词,那么就连一条有向边,求最长的长度. 分析:DAG的最长路和最短路在算法竞赛入门里边原原本本有的,结果我现在忘记了,,真是太弱了..方法就是,用map对应键值(以建图),然后删除操作和修改操作可以看做同一个操作,之后每个操作都是在相应的位置添加一个 '*' 就可以了.想说的有两点,一个是为什么删除和修改可以看做一个操作,其实删除这个操作根本就是多余的,因为一个单词

POJ - 2564 Edit Step Ladders

题意:题目按字典序给你多个字符串,判断如果一个字符串通过加,减,变一个字母的情况下可以变成另一个字符串的话,就代表他们之间有一个阶梯,求最多的阶梯 思路:首先我们应该想到这个有点LIS的感觉,然后我们可以采用记忆化搜索,然后就是每当一个字符串进行相应的变化后就去查找后面是否有这个字符串,依次找下去,判断最大值,重点是要通过HASH来优化 #include <iostream> #include <cstdio> #include <cstring> #include &

Gym 101246H ``North-East&#39;&#39;(LIS)

http://codeforces.com/gym/101246/problem/H 题意: 给出n个点的坐标,现在有一个乐队,他可以从任一点出发,但是只能往右上方走(包括右方和上方),要经过尽量多的点.输出它可能经过的点和一定会经过的点. 思路: 分析一下第一个案例,在坐标图上画出来,可以发现,他最多可以经过4个点,有两种方法可以走. 观察一下,就可以发现这道题目就是要我们求一个LIS. 首先,对输入数据排一下顺序,x小的排前,相等时则将y大的优先排前面. 用二分法求LIS,这样在d数组中就可

UVA - 10534Wavio Sequence(LIS)

题目:UVA - 10534Wavio Sequence(LIS) 题目大意:给出N个数字,找出这样的序列:2 * n + 1个数字组成.前面的n + 1个数字单调递增,后面n + 1单调递减. 解题思路:从前往后找一遍LIS,再从后往前找一遍LIS.最后只要i这个位置的LIS的长度和LDS的长度取最小值.再*2 - 1就是这个波浪数字的长度.注意这里的求LIS要用nlog(n)的算法,而且这里的波浪数字的对称并不是要求i的LIS == LDS,而是只要求LIS和LDS最短的长度就行了,长的那个

uva10723 - Cyborg Genes(LIS)

题目:uva10723 - Cyborg Genes(LIS) 题目大意:给出两个字符串,要求的到一个新的字符串,它保持了两个字符串的字符的特征,也就是可以在这个字符串中找到前两个字符串的子序列,求这样的字符串的最短长度和有多少种这样的不同的字符串. 解题思路:LIS.首先先要找出最长的公共子序列,这样得到的新的字符串的长度才会是最小:l1 + l2 - l[1][N]: l[i][j] :第一个字符串的前i个字符和第二个字符串的前j个字符的最长的公共子序列长度. n[i][j]: 使得第一个字

hoj_10001_朴素DP(LIS)

Longest Ordered Subsequence Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KB Total submit users: 1937, Accepted users: 1621 Problem 10001 : No special judgement Problem description A numeric sequence of ai is ordered if a1 < a2 <

最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)

最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj.例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列. 考虑最长公共子序列问题如何分解成

poj 3903 &amp; poj 2533 最长上升子序列(LIS)

最长上升子序列. 做这道题之前先做了2533,再看这道题,感觉两道题就一模一样,于是用2533的代码直接交, TLE了: 回头一看,数据范围.2533 N:0~1000:3903 N :1~100000. 原因终归于算法时间复杂度. 也借这道题学习了nlgn的最长上升子序列.(学习链接:http://blog.csdn.net/dangwenliang/article/details/5728363) 下面简单介绍n^2 和 nlgn 的两种算法. n^2: 主要思想:DP: 假设A1,A2..