Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

poj3898 Software Industry Revolution

$
0
0
Software Industry Revolution
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 263   Accepted: 86

Description

Making revolutions in the software industry is not an easy task. That’s why this problem is about something else. Stanescu has just invented a new super-cool way to develop software. It is similar to writing program code, but instead of writing it, you ask some else to do it. In such way, one could create great software, without even knowing what a Turing Machine is. As you can see, this is not just software industry revolution. Really, Stanescu does not care about the software industry at all. He just wants to make money. 
In order to protect the money he is going to make, he needs to pick a special password for his bank account, satisfying the following requirements: 


The password should not be too complex, so that Stanescu can remember it. The complexity of a password is the sum of the complexity of its characters and the complexity of a character is its position in the alphabet (for ’a’ it is 1, for ’b’ – 2, and so on). For example, the complexity of the string ”ala” is 1 + 12 + 1 = 14; 
It should match a given pattern string (composed of lowercase Latin letters, ’?’ and ’*’, no longer than 1000 characters). ’?’ is matched by one arbitrary lowercase Latin letter, and ’*’ – by zero or more arbitrary lowercase Latin letters; 
It should be a sub-string of given super-password string (composed of lowercase Latin letters, no longer than 10000). 


You have to write a program that computes the complexity of simplest possible password.

Input

Several test cases are given at the input. Each of them consists of a single line containing the pattern and the super-password strings separated by a white space.

Output

For each test case, your program should print a single line with one integer – the complexity of the simplest possible password. If no password satisfies the given requirements, the program should print -1.

Sample Input

a?a alabala
a*c?a axcbaabcbax

Sample Output

4
9

Hint

Explanation: 
Test case #1: aba is the simplest password 
Test case #2: abcba is simpler than axcba
这题考的是dp,可是我们一般很难写出状态转移方程,看解题报告还要看半天才知道什么意思,这个题我几乎就是copy解题报告的啊,虽然都是自己手打的,哎。。。。就当是解说员吧
/*
dp[i][j]代表模式串的第i个和原串的第j个匹配的时候最小值。
对于?
dp[i][j]=dp[i-1][j-1]+cost[j,j]

对于字母,要求mat[i]==pat[j]才能转移。
dp[i][j]=dp[i-1][j-1]+cost[j,j]
sum[i]代表原串前i个代价的总和
对于*
dp[i][j]=min{dp[i-1][k]+cost[k+1,j]}  for k>=0&&k<=j

对于这个式子的话看起来要枚举K,这样显然不行。
我们可以转化
dp[i-1][k]+cost[k+1,j]
=dp[i-1][k]+sum[j]-sum[k]=(dp[i-1][k]-sum[k])+sum[j]

(dp[i-1][k]-sum[k])这个是一个只和k有关的式子。
我们可以保存一个(dp[i-1][k]-sum[k])最小值。这样就可以o(1)得到dp[i][j]了。
*/
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std; 

char str[1050],pass[10050];
int sum[10050],record[27],dp[1005][10050];

int main ()
{
	int i,j,cur,n,m;
	bool flag;
	while(scanf("%s%s",str+1,pass+1)!=EOF)
	{
		n=strlen(str+1);
		m=strlen(pass+1);
		sum[0]=0;
		for(i=0;i<26;i++)
			record[i]=0;
		for(i=1;i<=m;i++)
		{
			record[pass[i]-'a']++;
		}
		for(i=1;i<=n;i++)
		{
			if(str[i]>='a')//没想到问题出在这,数组越界了oj尽然没提示RE却提示WA
				record[str[i]-'a']--;
		}
		for(i=0;i<26;i++)
		{
			if(record[i]<0)
				break;
		}
		if(i<26)//这是最开始的优化,明显不合题意的去掉
		{
			printf("-1\n");
			continue;
		}
		for(i=1;i<=m;i++)
		{
			sum[i]=pass[i]-'a'+1+sum[i-1];
		}
		for(i=0;i<=n;i++)
			for(j=0;j<=m;j++)
			dp[i][j]=10000000;
		for(i=0;i<=m;i++)//str[1]得特殊操作,给dp[1][j]一个初始值
		{
			if(i>0&&(str[1]=='?'||str[1]==pass[i]))//第一位为?或者和pass[i]相等那dp[1][i]当然就是str[1]对应的值也是sum[i]-sum[i-1]
			{
				dp[1][i]=sum[i]-sum[i-1];
			}
			else if(str[1]=='*')//*有点特殊,它的取值是不定的,但是这题要求最小的值,如果str第一个为*,那我们完全可以不取任何值,也就是0
			{
				dp[1][i]=0;
			}
		}
		for(i=2;i<=n;i++)
		{
			flag=0;
			if(str[i]=='*')
			{
				cur=10000000;
				if(dp[i-1][0]==0)
				{
					flag=1;
					dp[i][0]=0;
					cur=0;//记录一下最小值
				}
				for(j=1;j<=m;j++)
				{
					if(dp[i-1][j]-sum[j]<cur)
						cur=dp[i-1][j]-sum[j];
					if(sum[j]+cur<dp[i][j])
					{
						dp[i][j]=sum[j]+cur;
						flag=1;
					}
				}
			}
			else 
			{
				for(j=1;j<=m;j++)
				{
					if(dp[i-1][j-1]==10000000)
						continue;//简化运算
					if(str[i]=='?'||str[i]==pass[j])
					{
						if(dp[i][j]>dp[i-1][j-1]+pass[j]-'a'+1)
						{
							dp[i][j]=dp[i-1][j-1]+pass[j]-'a'+1;
							flag=1;
						}
					}
				}
			}
			if(!flag)//若flag为0,那就说明上面没有任何操作,没有符合条件的情况了,找不到适合的解了
				break;
		}
		if(i<=n)//程序没有全部执行,str并没有在pass中全部找到
		{
			printf("-1\n");
			continue;
		}
		cur=100000000;
		for(i=0;i<=m;i++)//应该是从零开始,如果str是*结果就是0
		{
			if(cur>dp[n][i])//str中的字母都找完了
				cur=dp[n][i];
		}
		if(cur==100000000)
			printf("-1\n");
		else 
			printf("%d\n",cur);
	}
	return 0;
}


作者:u011361299 发表于2013-7-19 13:17:42 原文链接
阅读:56 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>