题意:给你n个串,每个s【i】有一个权值val【i】,现在有两个操作

1,给你x,y,将编号为x的串的权值修改为y

2,给你x,问你编号为x的串对应多少【满足题目要求的串】

【满足题目要求的串】:对于一个字符串s【i】,如果s【x】是s【i】的后缀(比如s【x】是br,s【i】为abr),并且s【x】的权值大于等于s【i】的权值,那么s【i】就是满足题目要求的串

思路:

暴力思路:用v【i】记录s【i】对应的全部合法子串,每次执行2操作时遍历一遍v【i】求解

那么如何得到v数组呢?

首先把所有串都倒过来,这样后缀就变成了前缀,这样方便一些

然后用suffix【i】【j】记录第i个串前j个字符形成的子串的hash值,hash的话我用了130进制取模1e9+7

然后二重循环判断s【i】是否为s【j】的前缀

当s【i】的长度小于等于s【j】的长度时,设s【i】的长度为len,那么只需要判断suffix【i】【len】和suffix【j】【len】是否相等

当s【i】的长度大于s【j】的长度时,很明显s【i】一定不是s【j】的前缀

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef unsigned long long ull;
const int maxn = 1010;
const int mod = 1e9+7;
int T, n, q;
struct Date {
char s[maxn];
int val, len;
}date[maxn];
int suffix[maxn][maxn];
vector<int> v[maxn];
bool issuffix(int i, int j) {
if (date[i].len <= date[j].len && suffix[i][date[i].len-1] == suffix[j][date[i].len-1]) return true;
return false;
}
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) v[i].clear();
for (int i = 1; i <= n; i++) {
scanf("%s %d", date[i].s, &date[i].val);
date[i].len = strlen(date[i].s);
for (int j = 0, k = date[i].len - 1; j < k; j++, k--) swap(date[i].s[j], date[i].s[k]);
ull sum = 0;
for (int j = 0; j < date[i].len; j++) {
sum = (sum*130+date[i].s[j])%mod;
suffix[i][j] = sum;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (issuffix(i, j)) v[i].push_back(j);
}
}
scanf("%d", &q);
int op, x, y;
while (q--) {
scanf("%d", &op);
if (op == 1) {
scanf("%d %d", &x, &y);
date[x].val = y;
}
else {
scanf("%d", &x);
int ans = 0;
for (int i = 0; i < (int)v[x].size(); i++) {
if (date[v[x][i]].val <= date[x].val) ans++;
}
printf("%d\n", ans);
}
}
}
return 0;
}