每一行對話分別取匹配全部的表情ios
這樣是一個n**2的匹配,能夠用KMP 找出每行對話中的每一個表情的左右端點c++
這樣至關於就是問用最少多少個點 能夠覆蓋全部的區間(每一個區間中放一個點表示覆蓋)ide
貪心 按右端點升序排列 相同時左端點也升序(這裏其實沒有影響可是 按照匹配上來說 應該按照升序)spa
--理由:code
--> 若是當前所指區間的後面兩個區間的右端點相同 那麼應該是先比較左端點較小的那個區間 blog
可是由於後面兩個區間的右端點相同那麼必定是相互覆蓋的 因此對結果沒有影響get
而後 if (strict[crt].r < strict[next]) .l ) //區間不重疊string
{ans++; crt = next;} it
代碼君:io
#include <bits/stdc++.h> #include <string.h> #include <iostream> #include <stdio.h> using namespace std; const int MAXN = 107; const int MAXLEN = 107; char emo[MAXN][MAXLEN]; char str[MAXLEN]; struct S { int l, r; S() {} S(int l, int r) : l(l), r(r) {} bool operator < (S s1) const { if (r != s1.r) return r < s1.r; return l < s1.l; } }; int n, m; int nxt[MAXN << 1]; vector<S> v; void kmp_pre(char t[]) { int j, k; int tlen = strlen(t); k = -1, j = 0; nxt[0] = -1; while (j < tlen) { if (k == -1 || t[j] == t[k]) nxt[++j] = ++k; else k = nxt[k]; } } vector<int> kmp(char s[], char t[]) { int slen = strlen(s), tlen = strlen(t); vector<int> ret; int i = 0, j = 0; kmp_pre(t); while (i < slen) { if (j == -1 || s[i] == t[j]) { i++; j++; } else j = nxt[j]; if (j == tlen) { ret.push_back(i-1); j = nxt[j]; } } return ret; } int lidx[MAXN], ridx[MAXN]; int main() { //freopen("in.txt", "r", stdin); while (~scanf("%d%d", &n, &m)) { if (!n && !m) break; int ans = 0; for (int i = 0; i < n; i++) { scanf("%s", emo[i]); } getchar(); for (int i = 0; i < m; i++) { gets(str); v.clear(); for (int j = 0; j < n; j++) { vector<int> pos; int len = strlen(emo[j]); pos = kmp(str, emo[j]); for (int k = 0; k < pos.size(); k++) { v.push_back(S(pos[k]-len+1, pos[k])); } } sort(v.begin(), v.end());/* for (int i = 0; i < v.size(); i++) cout << v[i].l << " " << v[i].r << endl; return 0;*/ int crt = 0; if (!v.empty()) ans++; for (int j = 1; j < v.size(); j++) { if (v[j].l > v[crt].r) { crt = j; ans++; } } } cout << ans << endl; } return 0; }