/*
*区间贪心。前几天刚做了POJ 1328 ...思路完全相同...
*最多有100个表情,100行文字。遍历寻找每个表情的所在区间。时间复杂度大约在10^5 ~ 10^6 可以接受。
*然后对每个表情按照右坐标排序。改变表情的最右边的字符。贪心判断是否更改。
*(⊙o⊙)… 每一行的里的表情可能是重复的。所以判断每行要更改的最少字母数。最后求和。很傻逼的全都放一起了。然后。。。。幸福的wa了。
*/
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }