$n leq 100000$的一文本串,给$m leq 100000$个询问,每次问一小串在文本串的哪一个最短的子串里出现指定次数。注意,询问串互不相同,且总长度$leq 100000$。
比赛时不会分析复杂度QAQ没想到这么简单
互不相同的询问串,不同的长度会只有根号个。而每个长度的出现次数都是n级别的,因此总的出现次数是$nsqrt{n}$,只要想出$O(串长+出现次数)$的匹配算法就行了。
然后SA,SAM,AC,bitset挑个写就行了。写了AC。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 //#include<time.h> 5 //#include<complex> 6 #include<set> 7 //#include<queue> 8 #include<algorithm> 9 #include<stdlib.h> 10 using namespace std; 11 12 #define LL long long 13 int qread() 14 { 15 char c; int s=0; while ((c=getchar())<'0' || c>'9'); 16 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s; 17 } 18 19 //Pay attention to '-' , LL and double of qread!!!! 20 21 int n,lq; 22 #define maxn 200011 23 struct Edge{int to,next;}edge[maxn<<1]; int first[maxn],le=2; 24 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;} 25 26 set<int> ss[maxn]; int ls=0,bel[maxn]; 27 struct AC 28 { 29 struct Node{int ch[26],fail;}a[maxn]; 30 int num[maxn],size; 31 AC() {size=0; memset(a[0].ch,0,sizeof(a[0].ch));} 32 int insert(char *s,int id) 33 { 34 int now=0,m=strlen(s); 35 for (int i=0;i<m;i++) 36 { 37 int p=s[i]-'a'; 38 if (!a[now].ch[p]) 39 { 40 int x=++size; 41 a[now].ch[p]=x; 42 } 43 now=a[now].ch[p]; 44 } 45 num[id]=now; 46 return now; 47 } 48 49 int que[maxn],head,tail; 50 void makefail() 51 { 52 head=tail=0; 53 for (int i=0;i<26;i++) 54 { 55 int u=a[0].ch[i]; 56 if (u) que[tail++]=u,a[u].fail=0; 57 } 58 while (head!=tail) 59 { 60 int x=que[head++]; 61 for (int i=0;i<26;i++) 62 { 63 int u=a[x].ch[i]; 64 if (!u) {a[x].ch[i]=a[a[x].fail].ch[i]; continue;} 65 que[tail++]=u; 66 a[u].fail=a[a[x].fail].ch[i]; 67 } 68 } 69 } 70 void buildtree() {for (int i=1;i<=size;i++) in(a[i].fail,i);} 71 72 void pei(char *s) 73 { 74 int n=strlen(s),now=0; 75 for (int i=0;i<n;i++) 76 { 77 now=a[now].ch[s[i]-'a']; 78 if (!bel[now]) bel[now]=++ls; 79 ss[bel[now]].insert(i); 80 } 81 } 82 }ac; 83 84 int ques[maxn],kk[maxn],ll[maxn],ans[maxn]; 85 86 void bing(int x) 87 { 88 int Max=x; 89 for (int i=first[x];i;i=edge[i].next) 90 { 91 Edge &e=edge[i]; 92 bing(e.to); 93 if (ss[bel[e.to]].size()>ss[bel[Max]].size()) Max=e.to; 94 } 95 96 for (int i=first[x];i;i=edge[i].next) 97 { 98 Edge &e=edge[i]; if (e.to==Max) continue; 99 for (auto j=ss[bel[e.to]].begin();j!=ss[bel[e.to]].end();j++) ss[bel[Max]].insert(*j); 100 } 101 if (Max!=x) 102 { 103 for (auto j=ss[bel[x]].begin();j!=ss[bel[x]].end();j++) ss[bel[Max]].insert(*j); 104 bel[x]=bel[Max]; 105 } 106 107 if (ques[x]) 108 { 109 vector<int> p; 110 for (auto j=ss[bel[x]].begin();j!=ss[bel[x]].end();j++) p.push_back(*j); 111 int Ans=0x3f3f3f3f; 112 for (unsigned int k=kk[ques[x]],j=k-1;j<p.size();j++) Ans=min(Ans,p[j]-p[j-k+1]); 113 if (Ans==0x3f3f3f3f) ans[ques[x]]=-1; 114 else ans[ques[x]]=Ans+ll[ques[x]]; 115 } 116 } 117 118 char s[maxn],t[maxn]; 119 int main() 120 { 121 scanf("%s",s); n=strlen(s); 122 lq=qread(); 123 for (int i=1;i<=lq;i++) 124 { 125 kk[i]=qread(); 126 scanf("%s",t); ll[i]=strlen(t); 127 ques[ac.insert(t,i)]=i; 128 } 129 130 ac.makefail(); 131 ac.buildtree(); 132 ac.pei(s); 133 bing(0); 134 for (int i=1;i<=lq;i++) printf("%d ",ans[i]); 135 return 0; 136 }