Codeforces963C Frequency of String 【字符串】【AC自动机】

题目大意:

  给一个串s和很多模式串,对每个模式串求s的一个最短的子串使得这个子串中包含至少k个该模式串。

题目分析:

  均摊分析,有sqrt(n)种长度不同的模式串,所以有关的串只有msqrt(n)种。暴力用AC自动机找出来即可。

代码:

  

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 const int maxn = 102000;
  5 const int sigma = 26;
  6 
  7 int n,num,root,d[maxn],fa[maxn],fail[maxn],Ex[maxn];
  8 string str,query[maxn];
  9 vector<int> ans[maxn];
 10 
 11 int Number(char ch){return (int)(ch-'a');}
 12 
 13 struct trie{int data,end,nxt[sigma];}T[maxn];
 14 
 15 void insert(int now,int pla,int tnode){
 16     if(pla == query[now].size()){T[tnode].end=now;return;}
 17     int p = Number(query[now][pla]);
 18     if(T[tnode].nxt[p]){insert(now,pla+1,T[tnode].nxt[p]);}
 19     else{
 20     num++;T[tnode].nxt[p] = num;T[num].data = p;
 21     fa[num] = tnode; insert(now,pla+1,num);
 22     }
 23 }
 24 
 25 void read(){
 26     cin >> str >> n;
 27     for(int i=1;i<=n;i++){
 28     cin >> d[i] >> query[i];
 29     insert(i,0,root);
 30     }
 31 }
 32 
 33 queue <int> q;
 34 void BuildAC(){
 35     for(int i=0;i<sigma;i++) if(T[root].nxt[i]) q.push(T[root].nxt[i]);
 36     while(!q.empty()){
 37     int k = q.front();q.pop();
 38     int hh = fail[fa[k]];
 39     while(hh != root){
 40         if(T[hh].nxt[T[k].data]){fail[k]=T[hh].nxt[T[k].data];break;}
 41         else hh = fail[hh];
 42     }
 43     if(T[hh].nxt[T[k].data]&&(!fail[k])&&T[hh].nxt[T[k].data]!=k){
 44         fail[k]=T[hh].nxt[T[k].data];
 45     }
 46     for(int i=0;i<sigma;i++) if(T[k].nxt[i]) q.push(T[k].nxt[i]);
 47     }
 48 }
 49 
 50 void BuildExtraFail(){
 51     q.push(root);
 52     while(!q.empty()){
 53     int k = q.front();q.pop();
 54     int hh = fail[k];
 55     if(T[hh].end){Ex[k] = hh;}else Ex[k] = Ex[hh];
 56     for(int i=0;i<sigma;i++) if(T[k].nxt[i]) q.push(T[k].nxt[i]);
 57     }
 58 }
 59 
 60 void RunAC(){
 61     int now = root;
 62     for(int i=0;i<str.length();i++){
 63     int p = Number(str[i]);
 64     if(T[now].nxt[p]) now = T[now].nxt[p];
 65     else{
 66         int hh = fail[now];
 67         int fg = false;
 68         while(hh != root){
 69         if(T[hh].nxt[p]){fg=1;now=T[hh].nxt[p];break;}
 70         else hh = fail[hh];
 71         }
 72         if(fg == 1)goto loop;
 73         if(T[hh].nxt[T[p].data])now=T[hh].nxt[T[p].data];
 74         else now = root;
 75     }
 76     loop:int z = Ex[now];
 77     if(T[now].end) ans[T[now].end].push_back(i);
 78     while(z!=root){ans[T[z].end].push_back(i);z=Ex[z];}
 79     }
 80 }
 81 
 82 int Min(int a,int b){return a<b?a:b;}
 83 
 84 void work(){
 85     BuildAC();
 86     BuildExtraFail();
 87     RunAC();
 88     for(int i=1;i<=n;i++){
 89     if(ans[i].size()<d[i]){cout<<-1<<endl;continue;}
 90     int minn = 123456789;
 91     for(int j=d[i]-1;j<ans[i].size();j++){
 92         minn = Min(minn,ans[i][j]-ans[i][j-d[i]+1]+query[i].length());
 93     }
 94     cout<<minn<<endl;
 95     }
 96 }
 97 
 98 int main(){
 99     read();
100     work();
101     return 0;
102 }

猜你喜欢

转载自www.cnblogs.com/Menhera/p/8933790.html