CF963D Frequency of String【多串在母串的出現位置】

題目描述:

在這裏插入圖片描述
保證 mim_i 互不相同。

題目分析:

mim_iss 中的匹配次數是 O(Smi)O(|S|*\sqrt {\sum {m_i}}) 級別的。
證明可以用AC自動機來理解,設fail樹上每個點的祖先中結束節點的個數爲 xx,因爲長度各不相同,所以總長度至少爲 x(x+1)2\frac {x(x+1)}2,所以 xmix\le \sqrt {\sum {m_i}}。總共會遍歷 S|S| 個點的祖先。

原問題相當於是求所有匹配位置中相隔 kk 個的最近距離,求出所有匹配位置之後掃一遍即可。複雜度有保證。

求匹配位置可以 bitset。O(nmiw)O(\frac {n\sum m_i}w)
也可以AC自動機,預處理fail樹上第一個有結束節點的祖先 FailFail,用 ss 在自動機上走,每次跳 FailFail,把遇到的結束節點壓進對應的棧中,順便就可以求答案。O(n+nmi)O(n+n\sqrt{\sum m_i})

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);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章