标签:复杂 出现 size efi name 建立 push 通过 eof
解法看着吓人,其实就是为了优化ac自动机上暴力跳fail指针。。
另外这题对于复杂度的分析很有学习价值
/* 给定一个母串s,再给定n个询问(k,m) 对于每个询问,求出长度最小的t,使t是s的子串,且m作为子串在t中出现了m次 对多串建立ac自动机,然后用s去匹配,把所有询问的出现位置都用vector保存下来 然后对应每个询问的k进行更新答案 为了保证复杂度:在跳fail不能暴力向上跳,应该直接用一个指针pre跳到上一个带有询问的点 这样每次向上跳都让某个询问的vector更新进一个新的值 由于最多有sqrt(n)个不同的询问串长度,所以以每个s[i]为结尾的可匹配串也只有sqrt(n)个, 即最多在fail树上跳nsqrt(n)次 */ #include<bits/stdc++.h> using namespace std; #define N 200005 struct Query{ vector<int>pos; int k,len; }q[N]; char s[N],buf[N]; int n; struct Trie{ int nxt[N][26],fail[N],id[N],pre[N]; int root,L; int newnode(){ memset(nxt[L],-1,sizeof nxt[L]); id[L]=0; return L++; } void init(){L=0;root=newnode();} void insert(char buf[],int ID){ int len=strlen(buf); int now=root; for(int i=0;i<len;i++){ if(nxt[now][buf[i]-‘a‘]==-1) nxt[now][buf[i]-‘a‘]=newnode(); now=nxt[now][buf[i]-‘a‘]; } id[now]=ID; } void build(){ queue<int>q; fail[root]=root; for(int i=0;i<26;i++) if(nxt[root][i]==-1) nxt[root][i]=root; else { fail[nxt[root][i]]=root; q.push(nxt[root][i]); } pre[root]=0; while(q.size()){ int now=q.front();q.pop();//此时now的fail已经建立好 if(id[fail[now]]!=0)//找上一个询问的位置 pre[now]=fail[now]; else pre[now]=pre[fail[now]]; for(int i=0;i<26;i++) if(nxt[now][i]==-1) nxt[now][i]=nxt[fail[now]][i]; else { fail[nxt[now][i]]=nxt[fail[now]][i]; q.push(nxt[now][i]); } } } void query(char *s){ int len=strlen(s); int now=root; for(int i=0;i<len;i++){ now=nxt[now][s[i]-‘a‘]; //通过pre向上跳 int p=now; while(p){ q[id[p]].pos.push_back(i); p=pre[p]; } } } }ac; int main(){ ac.init(); scanf("%s",s); cin>>n; for(int i=1;i<=n;i++){ scanf("%d%s",&q[i].k,buf); q[i].len=strlen(buf); ac.insert(buf,i); } ac.build(); ac.query(s); //for(int i=1;i<=ac.L;i++) // cout<<ac.pre[i]<<" "; //处理每个询问 for(int i=1;i<=n;i++){ //cout<<q[i].pos.size()<<"\n"; if(q[i].pos.size()<q[i].k){ puts("-1");continue; } int ans=0x3f3f3f3f; for(int j=q[i].k-1;j<q[i].pos.size();j++){ ans=min(ans,q[i].pos[j]-q[i].pos[j-q[i].k+1]+q[i].len); } cout<<ans<<‘\n‘; } } /* aaabbbbaaabababab 27 2 aaabbbbaaaba 2 baaabab 1 abbbbaaabab 1 aabbbbaaabab 6 a 1 aaabbbbaaabababab 2 aaba 2 abbbba 5 aa 2 aaabbbb 2 abababa 3 aba 2 baaa 2 bbaaababa 1 aaabab 1 abbb 1 bbbbaaabababa 1 baaab 1 abbbbaaabababa 1 aaababa 1 ababab 2 abb 2 baaabababa 1 bbaaabababa 2 aaabb 1 abababab 4 bab */
标签:复杂 出现 size efi name 建立 push 通过 eof
原文地址:https://www.cnblogs.com/zsben991126/p/11701240.html