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 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
题意:给你一个递增的字符串数组,给你三种操作方法变成其他的串,问你最长的可能
思路:hash+二分,dp[i]表示从i开始的串的最长变化可能,记忆化搜索
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 25010;
const int HASH = 1000010;

int n, head[HASH], next[MAXN], f[MAXN];
char b[MAXN][20], temp[20];

int hash(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(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(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(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(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 = 1;
	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;
}

int main() {
	n = 0;
	memset(head, -1, sizeof(head));
	while (scanf("%s", b[n]) != EOF) {
		insert(n),++n;
	}
	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);
	return 0;
}

时间: 2024-10-09 03:43:22

UVA - 10029 Edit Step Ladders (二分+hash)的相关文章

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

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

UVA10029 - Edit Step Ladders(LIS)

题目大意:UVA10029 - Edit Step Ladders(LIS) 题目大意:给你一个按照字典序读入的单词,然后要求你找出最长的序列,要求这个最长的序列也要满足字典序,并且后一个是由前一个单词,由在任意的地方替换,增加,删除一个字符变换来的. 解题思路:LIS.但是这里的O(n^2) 25000,超时.但是查找符合的单词有个规律,符合变换要求的单词的长度是有要求的,必须相差小于等于1.并且数据中相同长度的单词不会超过45个,那么就可以把这些单词按照长度分类,那么查找的时候就是45 *

POJ - 2564 Edit Step Ladders

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

uva 10026 Problem C: Edit Step Ladders

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=970 通过对每一个字符串,每一个位置进行枚举三个操作,然后二分查找操作后的字符串是否存在,dp记录. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N 25

UVA - 12338 Anti-Rhyme Pairs 二分+hash

题目链接:https://vjudge.net/problem/UVA-12338 题意: 给你n个串 问你任意两个串的最大公共前缀长度是多少 题解: 二分+hash 思路很明显,我最近用来写hash 很鸡肋 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls

uva 10391 Compound Words (字符串-hash)

Problem E: Compound Words You are to find all the two-word compound words in a dictionary. A two-word compound word is a word in the dictionary that is theconcatenation of exactly two other words in the dictionary. Input Standard input consists of a

【BZOJ1414/3705】[ZJOI2009]对称的正方形 二分+hash

[BZOJ1414/3705][ZJOI2009]对称的正方形 Description Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究.最近,Orez又得到了一些数据,并已经把它们排成了一个n行m列的矩阵.通过观察,Orez发现这些数据蕴涵了一个奇特的数,就是矩阵中上下对称且左右对称的正方形子矩阵的个数. Orez自然很想知道这个数是多少,可是矩阵太大,无法去数.只能请你编个程序来计算出这个数. Input 文件的第一行为两个整数n和m.接下来n行每行包含m个正整数,表示Or

【二分+hash】【字符串】【平衡树】【JSOI 2008】火星人prefix

1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Submit: 4264 Solved: 1306 Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x, y)

UVA 10668 - Expanding Rods(数学+二分)

UVA 10668 - Expanding Rods 题目链接 题意:给定一个铁棒,如图中加热会变成一段圆弧,长度为L′=(1+nc)l,问这时和原来位置的高度之差 思路:画一下图可以很容易推出公式,设圆弧扇形部弧度r,那么可以计算出铁棒长度为lr/sin(r)这个公式在[0, pi/2]是单调递增的,所以可以用二分法去求解 要注意的一点是最后答案计算过程中带入mid,之前是带入x(二分的左边值),可实际上x是可能等于0的,而带入mid,由于是double型,所以mid实际上表示是一个非常趋近0