HDU 1936 区间贪心

/*
 *区间贪心。前几天刚做了POJ 1328 ...思路完全相同...
 *最多有100个表情,100行文字。遍历寻找每个表情的所在区间。时间复杂度大约在10^5 ~ 10^6 可以接受。
 *然后对每个表情按照右坐标排序。改变表情的最右边的字符。贪心判断是否更改。

 *(⊙o⊙)… 每一行的里的表情可能是重复的。所以判断每行要更改的最少字母数。最后求和。很傻逼的全都放一起了。然后。。。。幸福的wa了。
 */

  1 #include<stdio.h>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<string.h>
  5 using namespace std;
  6 
  7 char emo[110][20];
  8 char txt[110][110];
  9 int n, m;
 10 int cnt;
 11 int ans;
 12 
 13 struct E
 14 {
 15     int l, r;
 16 } e[10010];
 17 
 18 int cmp(E a, E b)
 19 {
 20     if (a.l != b.l)
 21         return a.l < b.l;
 22     return a.r < b.r;
 23 }
 24 
 25 void ask()
 26 {
 27     for (int i=0; i<m; ++i)  // 遍历文档
 28     {
 29         int lent = strlen(txt[i]);
 30         cnt = 1;
 31         for (int j=0; j<lent; ++j)
 32         {
 33             for (int k=0; k<n; ++k)  //遍历表情看是否在当前文档中
 34             {
 35                 bool flag = false;
 36                 int lene = strlen(emo[k]);
 37                 if (j+lene-1 > lent) continue;
 38                 if (txt[i][j] == emo[k][0] && txt[i][j+lene-1] == emo[k][lene-1])
 39                 {
 40                     flag = true;
 41                     for (int p=0; p<lene; ++p)
 42                     {
 43                         if (txt[i][j+p] != emo[k][p])
 44                         {
 45                             flag = false;
 46                             break;
 47                         }
 48                     }
 49                     if (flag)
 50                     {
 51                         e[cnt].l = j;
 52                         e[cnt++].r = j+lene-1;
 53                     }
 54                 }
 55             }
 56         }
 57        e[0].l = e[0].r = -100;  // 然而我也不太明白为什么要加上e[0]。
 58         sort(e+1, e+cnt, cmp); // 对每个表情按照区间右边的值从大到小排序。
 59 
 60         for (int i=cnt-1; i>=1; --i)  // 从后往前遍历。如果上一个的右端点小于当前左端点。ans++。破坏下一个的右端点。
 61         {
 62             if (e[i].l > e[i-1].r)
 63                 ans += 1;
 64             else
 65             {
 66                 for (int j=i-1; j>=1; --j)  // 否则直到找到第一个右端点小于当前左端点的位置。破坏它的右端点。ans++。
 67                 {
 68                     if (e[i].l <= e[j].r);
 69                     else
 70                     {
 71                         i = j+1;  // 循环结束后还要i--。所以i= j+1。 实际上就是i = j。
 72                         ans += 1;
 73                         break;
 74                     }
 75                 }
 76             }
 77         }
 78 
 79     }
 80 }
 81 
 82 int main()
 83 {
 84     while(cin >> n >> m)
 85     {
 86         if (n == 0 && m == 0) break;
 87         for (int i=0; i<n; ++i)
 88         {
 89             cin >> emo[i];
 90         }
 91         getchar();
 92         for (int i=0; i<m; ++i)
 93         {
 94             gets(txt[i]);
 95         }
 96         ans = 0;
 97         ask();  //遍历寻找每个表情的区间范围
 98         cout << ans << endl;
 99     }
100     return 0;
101 }
View Code



原文地址:https://www.cnblogs.com/icode-girl/p/4683425.html