https://ac.nowcoder.com/acm/problem/14612
题意:也很简单,就是加入一些字符串,然后查询在特定的串的出了多少次,并不是多少个;
做法:这道题肯定不能用普通的KMP,其他KMP我就不知道了,首先想到的就是AC自动机,但不过我们学的AC自动机都没有中间加入字符串的功能,我首先想到的就是,暴力建Trie果不其然直接T了,然后看了一下大佬的代码,他是按照二进制的拆分建的Trie,我认为建树的复杂度应该差不多,区别就在于查找的复杂度,这次学到了。
还有就是输入数据量比较大char不好处理,建议用string
好像还有什么,dfs序+AC自动机+树状数组的做法,反正不会。。。。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=20;
const int MX=1e6+10;
struct bits_Aho_trie
{
int next[MX][26],endd[MX],fail[MX];
int root[MAXN],siz[MAXN],gcnt,ncnt,scnt;
string str[300010];
void init()
{
memset(root,0,sizeof(root));
memset(siz,0,sizeof(siz));
ncnt=gcnt=scnt=0;
}
int newnode()
{
endd[++ncnt]=fail[ncnt]=0;
memset(next[ncnt],0,sizeof(next[ncnt]));
return ncnt;
}
void build(int rt)
{
fail[rt]=rt;
queue<int>qu;
for(int i=0;i<26;i++)
{
if(next[rt][i]) fail[next[rt][i]]=rt,qu.push(next[rt][i]);
else next[rt][i]=rt;
}
while(!qu.empty())
{
int u=qu.front();qu.pop();
endd[u]+=endd[fail[u]];
for(int i=0;i<26;i++)
{
if(next[u][i])
fail[next[u][i]]=next[fail[u]][i],qu.push(next[u][i]);
else
next[u][i]=next[fail[u]][i];
}
}
}
void rebuild(int l,int r,int rt)
{
rt=newnode();
for(int i=l;i<=r;i++)
{
int p=rt;
for(int j=0;j<str[i].size();j++)
{
if(next[p][str[i][j]-'a']==0)
next[p][str[i][j]-'a']=newnode();
p=next[p][str[i][j]-'a'];
}
endd[p]++;
}
build(rt);
}
void Insert(string s)
{
str[++scnt]=s;
siz[++gcnt]=1,root[gcnt]=newnode();
while(gcnt>=2&&siz[gcnt-1]==siz[gcnt])
siz[--gcnt]*=2;
ncnt=root[gcnt]-1;
rebuild(scnt-siz[gcnt]+1,scnt,root[gcnt]);
}
int rquery(int rt,string s)
{
int res=0,p=rt;
for(int i=0;i<s.size();i++)
{
p=next[p][s[i]-'a'];
res+=endd[p];
}
return res;
}
int query(string s)
{
int res=0;
for(int i=1;i<=gcnt;i++)
res+=rquery(root[i],s);
return res;
}
}ac;
string tmp;
int n,m,T;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>T;
while(T--)
{
ac.init();
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>tmp;
ac.Insert(tmp);
}
for(int i=0;i<m;i++)
{
int x;
cin>>x>>tmp;
if(x==1)
ac.Insert(tmp);
else
cout<<ac.query(tmp)<<endl;
}
}
return 0;
}
/**
2
1 3
abc
2 abcabc
1 aba
2 abababc
6 2
abc
bcd
abcd
bcd
abcd
abcd
2 abc
2 bcd
*/