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 }