洛谷链接:Death DBMS - 洛谷
解法:考虑朴素的AC自动机,注意由于字符串会重复,需要用multiset来记录val,这个代码TLE在第87个点。
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+5;
int ch[maxn][26],fail[maxn],tot,ed_pos[maxn], val[maxn]; //ed_pos数组用来记录每个字符串结束位置,val数组用来记录每个s的val
multiset<int> st[maxn]; //记录所有val
int n,m; string s;
string ss[maxn];
inline void build(int idx, const string&s){
int len=s.size(), x, u=0;
for(int i=0; i<len; i++){
x=s[i]-'a';
if(!ch[u][x]) ch[u][x] = ++tot; //如果没有这个点,就建立
u=ch[u][x];
}
ed_pos[idx]=u; //记录结束位置
st[u].insert(0);
val[idx] = 0;
}
inline void get_fail(){
queue<int> q;
for(int i=0; i<26; i++) //特别处理第一层
if(ch[0][i]) q.push(ch[0][i]); //第一层结点加入队列
while(q.size()){ //bfs求fail指针
int u=q.front(); q.pop(); //父结点
for(int i=0; i<26; i++){
if(ch[u][i]){ //有这个子结点
fail[ch[u][i]] = ch[fail[u]][i]; //fail = fafail->child
q.push(ch[u][i]);
} else {ch[u][i] = ch[fail[u]][i];} //特殊处理,建立虚拟子结点,实际上相当于失配
}
}
}
inline void change(int x,int y){
int u = ed_pos[x];
st[u].erase(st[u].find(val[x]));
st[u].insert(y);
val[x] = y; //最后别忘记把val数组里的改了
}
inline void ask(const string&s){
int u=0, res=-1;
for(char c:s){
u=ch[u][c-'a'];
for(int t=u; t; t=fail[t]){
if(st[t].size()) res=max(res,*st[t].rbegin());
}
}
cout<<res<<'\n';
}
int main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(val,-1,sizeof(val));
cin>>n>>m; for(int i=1; i<=n; i++) {cin>>s; ss[i]=s; build(i,s);}
get_fail();
for(int i=1; i<=m; i++){
int q,x,y; cin>>q;
if(q==1) {cin>>x>>y; change(x,y);}
else {cin>>s; ask(s);}
}
}