Frequency-of-String-cf963

题目

题目链接

内容

给出字符串s, s 1 e 5 |s|\le 1e^5 ,有n个询问,每个询问给出字符串 m i m_i ,和整数 k i k_i (每个字符串都不相同),求s的一个子串,字符串 m i m_i 出现了 k i k_i 次,求子串的最短长度,如果不存在这样的子串输出-1.

1 n m i 1 e 5 \sum_1^n |m_i|\le1e^5

分析

用n个询问的字符串 m i m_i 建AC自动机.

我们定义match数组:match[i]为i节点的最长后缀,并且这个后缀是n个询问串中的一个.如果不存在这样的后缀那么match[i]为AC自动机的根节点.

由于限制了询问字符串的总长度,而长度不同的字符串不超过 1 n m i \sqrt{\sum_1^n|m_i|} 个.

我们可以在 O ( n n ) O(n\sqrt n) 内找出所有询问串的出现位置存入pos数组,最后遍历pos数组得出答案.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define debug(x) cerr<<#x<<' '<<x<<'\n'
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
const int maxn=1e5+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
struct Trie {
    int next[maxn][26],fail[maxn],id[maxn],root,cnt;
    int match[maxn];
    int newnode() {
        rep(i,0,25) next[cnt][i]=-1;
        id[cnt++]=0;
        return cnt-1;
    }
    void init() {
        cnt=0;
        root=newnode();
    }
    void ins(char a[],int x) {
        int len=strlen(a),now=root;
        rep(i,0,len-1) {
            if(next[now][a[i]-'a']==-1)
                next[now][a[i]-'a']=newnode();
            now=next[now][a[i]-'a'];
        }
        id[now]=x;
    }
    void build() {
        queue<int> q;
        fail[root]=root;
        rep(i,0,25) {
            if(next[root][i]==-1) {
                next[root][i]=root;
            }
            else {
                fail[next[root][i]]=root;
                match[next[root][i]]=root;
                q.push(next[root][i]);
            }
        }
        while(!q.empty()) {
            int now=q.front();
            q.pop();
            rep(i,0,25) {
                if(next[now][i]==-1) next[now][i]=next[fail[now]][i];
                else {
                    fail[next[now][i]]=next[fail[now]][i];
                    q.push(next[now][i]);
                    int tmp=fail[next[now][i]];
                    if(id[tmp]>0) match[next[now][i]]=tmp;
                    else match[next[now][i]]=match[tmp];
                }
            }
        }
    }
}AC;
vi pos[maxn];
char str[maxn],a[maxn];
int k[maxn],lena[maxn];
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);
    cin>>str;
    int n;
    cin>>n;
    AC.init();
    rep(i,1,n) {
        cin>>k[i]>>a;
        lena[i]=strlen(a);
        AC.ins(a,i);
    }
    AC.build();
    int len=strlen(str),now=0;
    rep(i,0,len-1) {
        now=AC.next[now][str[i]-'a'];
        for(int t=now;t;t=AC.match[t]) {
            if(AC.id[t]) pos[AC.id[t]].pb(i);
        }
    }
    rep(i,1,n) {
        if(k[i]>pos[i].size()) cout<<-1<<'\n';
        else {
            int ans=inf;
            for(int l=0,r=k[i]-1;r<pos[i].size();l++,r++) {
                ans=min(ans,pos[i][r]-pos[i][l]+lena[i]);
            }
            cout<<ans<<'\n';
        }
    }
    return 0;
}
 
发布了10 篇原创文章 · 获赞 0 · 访问量 326

猜你喜欢

转载自blog.csdn.net/WA_King/article/details/104089591
今日推荐