1.暴力 10/12
#include <bits/stdc++.h> using namespace std; int n; string a[10005]; int main() { cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; string ll; cin >> ll; for (int i = 0; i < n; i++) { string u = a[i]; int num = 0; int j = 0; for (int k = 0; k < ll.size(); k++) { if (ll[k] == a[i][j]) { num++; j++; } } if (num == a[i].size()) { cout << "YES" << endl; } else cout << "NO" << endl; } }
2.记录每个字母(共26个)的位置下标,并分别存在各自的字母下标数组中(例:a数组:1 3 5;b数组:2 6)
找一个字母的位置,即在此字母的下标数组中找(靠近左边的)&&(>前一个字母下标的数字)
(即若单词为bab,则先找b数组中最左侧位置2,再找a数组中>2&&最左侧的数字3,再找b数组中>3&&最左侧的数字6。如果都能找到位置,则说明此单词在歌词中)
#include <bits/stdc++.h> using namespace std; const int N = 1e4 + 10; int n, l, r, mid, ans; string a[N], ll; vector<int> abc[27]; // 字母下标数组 int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; string ll; cin >> ll; for (int i = 0; i < ll.size(); i++) abc[ll[i] - 'a'].push_back(i); // 在各字母表中记录位置下标 for (int i = 1; i <= n; i++) { int len = a[i].size(), now = -1; // now记录此时字母的位置应在now右侧 int flag = 1; for (int j = 0; j < len; j++) { l = 0, r = abc[a[i][j] - 'a'].size() - 1, ans = -1; // 二分字母下标数组。找字母下标 while (l <= r) { mid = (l + r) / 2; if (abc[a[i][j] - 'a'][mid] > now) { r = mid - 1, ans = mid; } else l = mid + 1; } if (ans == -1)//不能找到一个位置使此单词的某一字母在歌词中 { flag = 0; break; } now = abc[a[i][j] - 'a'][ans];//now更新为此字母当前位置,下一字母的位置应在now之后 } if (flag) { cout << "YES" << endl; } else cout << "NO" << endl; } }