HDOJ 4271 Find Black Hand(最短编辑距离)

/*
A一道题,真心觉得不容易,各种情况要考虑。不过是一道经典DP问题
首先这道题,是一道最短编辑路径问题,很久以前做过这类问题,一直没做了,所以看到这道题时候根本没有往DP方面想。
d[i][j]表示,母串ss[i]得到子串s[j]的最小编辑次数,并且i与前面的操作相连。
然后这道题,可以出现环,具体处理将母串复制一遍添加到后面。
但是同一个字母不能用多次,所以需要分情况处理。比如母串:abcd,子串:abcda,本来应该输出 abcda 1
母串长度为len_ss,子串长度为len_s,如果len_ss > len_s * 2,则上面那种情况一定不会出现,因为出现那种情况编辑距离肯定大于len_s
否则的话,另外处理,每次从母串ss[]中截取len_ss长度字符串进行操作。
*/

#include <cstdio>
#include <cstring>
const int mMax = 200005;
const int nMax = 15;
int d[mMax][nMax];
char ss[mMax];
char s[nMax][nMax];
int N;

int min(int a, int b, int c)
{
	if(a <= b && a <= c) return a;
	if(b <= a && b <= c) return b;
	return c;
}

int main()
{
	while(scanf("%s", ss + 1) != EOF)
	{
		scanf("%d", &N);
		int i, j, k, l;
		for(i = 0; i < N; ++ i) scanf("%s", s[i] + 1);
		int len_ss = strlen(ss + 1);
		memcpy(ss + len_ss + 1, ss + 1, len_ss * sizeof(char));
		int _max = nMax, x = 0;
		for(i = 0; i < N; ++ i)
		{
			int len_s = strlen(s[i] + 1);
			for(j = 0; j <= len_s; ++ j)
				d[0][j] = j;
			for(j = 0; j <= len_ss * 2; ++ j)
				d[j][0] = 0;
			if(len_ss > 2 * len_s)
			{
				for(j = 1; j <= 2 * len_ss; ++ j)
				{	
					for(k = 1; k <= len_s; ++ k)
					{
						if(ss[j] == s[i][k])
							d[j][k] = min(d[j - 1][k - 1], d[j][k - 1] + 1, d[j - 1][k] + 1);
						else
							d[j][k] = min(d[j - 1][k - 1] + 1, d[j][k - 1] + 1, d[j - 1][k] + 1);
					}
					if(d[j][k - 1] < _max)
					{
						_max = d[j][k - 1];
						x = i;
					}
					else if(d[j][k - 1] == _max && (strcmp(s[i] + 1, s[x] + 1) < 0))
					{
						x = i;
					}
				}
			}
			else
			{
				for(l = 1; l <= len_ss; ++ l)
				{
					for(j = 0; j <= len_s; ++ j)
						d[l - 1][j] = j;
					for(j = l; j <= l + len_ss - 1; ++ j)
						d[j][0] = 0;
					for(j = l; j <= l + len_ss - 1; ++ j)
					{	
						for(k = 1; k <= len_s; ++ k)
						{
							if(ss[j] == s[i][k])
								d[j][k] = min(d[j - 1][k - 1], d[j][k - 1] + 1, d[j - 1][k] + 1);
							else
								d[j][k] = min(d[j - 1][k - 1] + 1, d[j][k - 1] + 1, d[j - 1][k] + 1);
						}
						if(d[j][k - 1] < _max)
						{
							_max = d[j][k - 1];
							x = i;
						}
						else if(d[j][k - 1] == _max && (strcmp(s[i] + 1, s[x] + 1) < 0))
						{
							x = i;
						}
					}
				}
			}
			
		}
		printf("%s %d\n", s[x] + 1, _max);
	}
	return 0;
}

你可能感兴趣的:(c)