poj3267(The Cow Lexicon)

题目地址:The Cow Lexicon

题目大意:

   奶牛有自己的识别单词的语言,它有自己的字典序列,如果给一串字符不符合奶牛的字典里的单词,奶牛就无法识别,你的任务就是找出给的字符串中包含给出奶牛字典的单词,至少从主串里删除几个字符,使主串只包含奶牛字典里的单词,不包含多于的字符。

解题思路:

    动态规划dp。 DP一直都不太懂,不看解题报告根本推不出来状态方程,入门水平都不够,需要好好练习学习该知识点。

状态方程: dp[i] i 代表从i到L最少需要删除的字符个数。

首先分为两种思想:

     一是不能匹配成功  : dp[i]=dp[i+1]+1;(从后往前推)

     二是匹配成功:        dp[i]=min(dp[i],dp[p1+1]+p1+1-i-len);

解释一下第二个式子:

    dp[p1+1]+p1+1-i-len.    因为能够匹配成功,从字符串数组 i 开始匹配,p1代表和字典字符串匹配结束位于主串的位置。 p1+1-i 代表主串用了多少个字符与字典字符串匹配成功。然后-len 代表需要删除的字符个数,然后 + dp[p1+1] 意为加上从p1+1位置到L的最小删除的个数。  所以整个式子代表dp[i]匹配成功时最少删除的个数。  因为从主串 i 位置到p1位置可能匹配很多次奶牛字典字符串,这时我们应该选取较小的dp[i]。

代码:

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <sstream>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cstdio>
 7 #include <string>
 8 #include <bitset>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <cmath>
13 #include <list>
14 #include <map>
15 #include <set>
16 using namespace std;
17 /***************************************/
18 #define ll long long
19 #define int64 __int64
20 #define PI 3.1415927
21 /***************************************/
22 const int INF = 0x7f7f7f7f;
23 const double eps = 1e-8;
24 const double PIE=acos(-1.0);
25 const int d1x[]= {0,-1,0,1};
26 const int d1y[]= {-1,0,1,0};
27 const int d2x[]= {0,-1,0,1};
28 const int d2y[]= {1,0,-1,0};
29 const int fx[]= {-1,-1,-1,0,0,1,1,1};
30 const int fy[]= {-1,0,1,-1,1,-1,0,1};
31 /*vector <int>map[N];map[a].push_back(b);int len=map[v].size();*/
32 /***************************************/
33 void openfile()
34 {
35     freopen("data.in","rb",stdin);
36     freopen("data.out","wb",stdout);
37 }
38 priority_queue<int> qi1;
39 priority_queue<int, vector<int>, greater<int> >qi2;
40 /**********************华丽丽的分割线,以上为模板部分*****************/
41 int min(int a,int b)
42 {
43     if (a<b)
44         return a;
45     return b;
46 }
47 int main()
48 {
49     int n,m;
50     while(scanf("%d%d",&m,&n)!=EOF)
51     {
52         char s1[305],s2[605][305];
53         int dp[305];
54         memset(s1,0,sizeof(s1));
55         memset(s2,0,sizeof(s2));
56         memset(dp,0,sizeof(dp));
57         int i,j;
58         scanf("%s",s1);
59         for(i=0; i<m; i++)
60             scanf("%s",s2[i]);
61         int len1=strlen(s1);
62         dp[len1]=0;
63         for(i=len1-1; i>=0; i--)
64         {
65             dp[i]=dp[i+1]+1;
66             for(j=0; j<m; j++)
67             {
68                 int len2=strlen(s2[j]);
69                 int p1=i;
70                 int p2=0;
71                 while(len1-i>=len2&&s1[i]==s2[j][0])
72                 {
73                     if (s1[p1++]==s2[j][p2])
74                     {
75                         p2++;
76                     }
77                     if (p2==len2)
78                     {
79                         dp[i]=min(dp[i],dp[p1]+p1-i-len2); //这里没有p1+1,原因:p1++;
80                         break;
81                     }
82                     if(p1>=len1)
83                         break;
84 
85                 }
86             }
87         }
88         printf("%d
",dp[0]);
89     }
90     return 0;
91 }
View Code
屌丝终有逆袭日,*******。
原文地址:https://www.cnblogs.com/ZhaoPengkinghold/p/3886745.html