http://codeforces.com/gym/101138/problem/A
感觉有一种套路就是总长度 <= 某一个数的这类题,大多可以分块
首先把集合串按长度分块,对于每一个询问串,
在 > magic的big集合里,因为最多sqrtn个,可以暴力枚举每一个,然后暴力枚举询问串的每一个长度是其的子串,判断是否相等
在 <= magic的small集合里,枚举每一个长度是magic, magic-1, magic-2, magic-3........1的字符串,然后看看是否在small集合里存在
small集合用unordermap保存即可。
ps
判断map是否存在一个元素,用mp.find
不然用mp[]每次都会生成一个节点,然后MLE, 清空用mp.erase
不然Mp.find是true的

#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef unsigned long long int ULL; const int seed = 131; const int maxn = 200000 + 20; struct Node { ULL hs; int lenstr; Node(ULL _hs, int _lenstr) { hs = _hs, lenstr = _lenstr; } bool operator < (const Node & rhs) const { if (hs != rhs.hs) return hs > rhs.hs; else return lenstr > rhs.lenstr; } }; vector<Node> all; set<Node> ss; unordered_map<ULL, bool> mp; char str[maxn]; int magic; set<Node> :: iterator it; void addchar(int id, char ch) { // set<Node> :: iterator it; if (all[id].lenstr > magic) { ss.erase(ss.find(all[id])); all[id].lenstr++; all[id].hs = all[id].hs * seed + ch; ss.insert(all[id]); } else { if (all[id].lenstr == magic) { mp.erase(all[id].hs); // mp[all[id].hs] = false; all[id].lenstr++; all[id].hs = all[id].hs * seed + ch; ss.insert(all[id]); } else { mp.erase(all[id].hs); all[id].lenstr++; all[id].hs = all[id].hs * seed + ch; mp[all[id].hs] = true; } } } ULL po[maxn]; ULL sum[maxn]; int last_yes; bool ok() { int lenstr = strlen(str + 1); for (int i = 1; i <= lenstr; ++i) { str[i] = (str[i] - 'a' + last_yes) % 26 + 'a'; sum[i] = sum[i - 1] * seed + str[i]; } for (it = ss.begin(); it != ss.end(); ++it) { int len = it->lenstr; for (int j = len; j <= lenstr; ++j) { if (it->hs == sum[j] - po[len] * sum[j - len]) return true; } } for (int i = 1; i <= lenstr; ++i) { for (int c = 1; c <= magic && c <= i; ++c) { if (mp.find(sum[i] - po[c] * sum[i - c]) != mp.end()) return true; } } return false; } void work() { int n, q; scanf("%d%d", &n, &q); magic = (int)sqrt(n * 1.0); for (int i = 1; i <= n; ++i) { scanf("%s", str + 1); ULL hashVal = 0; int lenstr = strlen(str + 1); for (int j = 1; j <= lenstr; ++j) { hashVal = hashVal * seed + str[j]; } if (lenstr > magic) ss.insert(Node(hashVal, lenstr)); else { mp[hashVal] = true; } all.push_back(Node(hashVal, lenstr)); } last_yes = 0; for (int i = 0 ; i < q; ++i) { int op; scanf("%d", &op); if (op == 2) { int index, ch; scanf("%d%d", &index, &ch); addchar((index + last_yes) % n, (ch + last_yes) % 26 + 'a'); } else { scanf("%s", str + 1); if (ok()) { printf("YES "); last_yes = i; } else printf("NO "); } } } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif po[0] = 1; for (int i = 1; i <= maxn - 2; ++i) po[i] = po[i - 1] * seed; work(); return 0; }