Software Industry Revolution

来源:互联网 发布:堆排序算法java实现 编辑:程序博客网 时间:2024/05/16 23:57
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);    }}


原创粉丝点击