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[0][0]即賦為零,這種特殊情況下的邊界條件沒怎
麼考慮清楚,導致wa了很多次,調了很久。
題目大意我就不多說了,這道題我所採用的是dp,我和很多人
一樣,開始也想不到,不過確實可以這樣做的
x[i]='?'或者 x[i]=y[j] dp[i][j]=dp[i-1][j-1]+y[j]-'a'+1
x[i]='*' dp[i][j]=dp[i-1][k]+sum[j]-sum[k] 將等式變形,
可得dp[i][j]=(dp[i-1][k]-sum[k]) + sum[j];
注意:這裡,很多人想到了單調隊列,我試過了,逾時,
其實,這裡不需要的,‘*’可以代表任意長的字串,所以,
只需要用now保留一個最小值就行,這樣是玩玩全全的O(1)
層級
coding:
# include<stdio.h># include<string.h># define inf 100000000# define min(a,b) (a<b?a:b)int dp[1005][10005];int main(){ char x[1005],y[10005]; int sum[10005]; int i,j,k; bool p; while (~scanf("%s%s",x,y)) { int lx,ly; lx=strlen(x); ly=strlen(y); for (i=ly;i>=1;i--) y[i]=y[i-1]; //整體往後挪一位 sum[1]=y[1]-'a'+1; for (i=1;i<=ly;i++) { sum[i]=sum[i-1]+y[i]-'a'+1; //求出初始位到當前位字母之和 } for (i=0;i<lx;i++) for (j=0;j<=ly;j++) dp[i][j]=inf; for (i=0;i<=ly;i++) { if (i>0&&(x[0]=='?'||x[0]==y[i])) dp[0][i]=y[i]-'a'+1; else if (x[0]=='*') { dp[0][i]=0; //將原串首位初始化 } } for (i=1;i<lx;i++) { p=false; if ((x[i]>='a'&&x[i]<='z')||x[i]=='?') { for (j=1;j<=ly;j++) { if (dp[i-1][j-1]==inf) continue; if (x[i]==y[j]||x[i]=='?') { dp[i][j]=dp[i-1][j-1]+y[j]-'a'+1; p=true; } } } else { int now=inf; if (dp[i-1][0]==0) { dp[i][0]=dp[i-1][0]; //這步很容易忘記哦 now=0; } p=true; for (j=1;j<=ly;j++) { now=min(now,dp[i-1][j]-sum[j]); //不斷更新最小值 if (now+sum[j]<dp[i][j]) { dp[i][j]=now+sum[j]; } } } if (!p) break; } int ans=inf; for (j=0;j<=ly;j++) { ans=min(ans,dp[lx-1][j]); } if (ans==inf) ans=-1; printf("%d\n",ans); }}