Question address: http://poj.org/problem? Id = 3898
Question meaning:
Give you a pattern string, and give you an original string to match
In the mode string? Can correspond to any character
* Can contain 0 or more characters.
Where a = 1, B = 2... you need to find the minimum value that can be matched in the original string.
Output-1 if not.
This is a DP question. It is actually very similar to LCS, but I was thinking about various matching algorithms during the competition.
Nima DP is just a dead end.
Solution:
Use DP [I] [J] to represent the value when the I of the pattern string matches the J of the original string.
It cannot match. It is INF.
So there are several transferred
For ?, DP [I] [J] = DP [I-1] [J-1] + cost [J]
For characters, if S1 [I] = S2 [J], DP [I] [J] = DP [I-1] [J-1] + cost [J]
For *, because * can correspond to 0 or more
Then DP [I] [J] = DP [I] [J] = min {DP [I-1] [k] + sum (cost [k] ~ Cost [J])}
Optimization for the third type
Because sum (cost [k] ~ Cost [J]) = sum [J]-sum [K], so we use a cur to maintain the minimum value of DP [I-1] [k]-sum [k]
Then sum [J] is added, and then a dimension is dropped.
It's really amazing. Although DP is sometimes difficult, I figured out that there is something wonderful in it.
The code below:
# Include <cstdio> # include <cstring> # include <algorithm> using namespace STD; const int maxn = 1010; char S1 [maxn]; char S2 [maxn * 10]; int DP [maxn] [maxn * 10]; int sum [maxn * 10]; const int INF = 0x3f3f3f3f; int main () {While (~ Scanf ("% S % s", & S1 [1], & S2 [1]) {int len1 = strlen (& S1 [1]); int len2 = strlen (& S2 [1]); sum [0] = 0; For (INT I = 1; I <= len2; I ++) sum [I] = sum [I-1] + (s2 [I]-'A' + 1); For (INT I = 0; I <= len1; I ++) for (Int J = 0; j <= len2; j ++) DP [I] [J] = inf; // For the original string that can be used as a header, initialize for (INT I = 0; I <= len2; I ++) {if (I> 0 & (S1 [1] = '? '| S1 [1] = S2 [I]) DP [1] [I] = sum [I]-sum [I-1]; else if (S1 [1] = '*') DP [1] [I] = 0;} bool flag = true; For (INT I = 2; I <= len1; I ++) {flag = false; If (S1 [I] = '*') {int cur = inf; if (DP [I-1] [0] = 0) {DP [I] [0] = 0; cur = 0; flag = true ;} for (Int J = 1; j <= len2; j ++) {If (DP [I-1] [J]-sum [J] <cur) cur = DP [I-1] [J]-sum [J]; If (cur + sum [J] <DP [I] [J]) DP [I] [J] = cur + sum [J], flag = true ;}} else {for (Int J = 1; j <= Len2; j ++) {If (DP [I-1] [J-1] = inf) continue; If (S1 [I] = '? '| S2 [J] = S1 [I]) {DP [I] [J] = min (DP [I] [J], DP [I-1] [J-1] + S2 [J]-'A' + 1); flag = true ;}} if (! Flag) break;} If (! Flag) {puts ("-1"); continue;} int ans = inf; For (INT I = 1; I <= len2; I ++) ans = min (ANS, DP [len1] [I]); If (ANS =-1) puts ("-1 "); else printf ("% d \ n", ANS);} return 0 ;}