題目描述:
保證 互不相同。
題目分析:
在 中的匹配次數是 級別的。
證明可以用AC自動機來理解,設fail樹上每個點的祖先中結束節點的個數爲 ,因爲長度各不相同,所以總長度至少爲 ,所以 。總共會遍歷 個點的祖先。
原問題相當於是求所有匹配位置中相隔 個的最近距離,求出所有匹配位置之後掃一遍即可。複雜度有保證。
求匹配位置可以 bitset。
也可以AC自動機,預處理fail樹上第一個有結束節點的祖先 ,用 在自動機上走,每次跳 ,把遇到的結束節點壓進對應的棧中,順便就可以求答案。
Code:
#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
int n,m,Q;
char s[maxn],t[maxn];
bitset<maxn>a[26],ans;
int main()
{
scanf("%s%d",s,&Q),n=strlen(s);
for(int i=0;i<n;i++) a[s[i]-'a'].set(i);
for(int k,sz;Q--;){
scanf("%d%s",&k,t),m=strlen(t);
ans.set();
for(int i=0;i<m;i++) ans&=a[t[i]-'a']>>i;
if((sz=ans.count())<k) {puts("-1");continue;}
int len=maxn,l=ans._Find_first(),r=ans._Find_first();
for(int i=1;i<k;i++) r=ans._Find_next(r);
for(int i=k;i<=sz;i++) len=min(len,r-l+m),l=ans._Find_next(l),r=ans._Find_next(r);
printf("%d\n",len);
}
}