Gym - 101741K Consistent Occurrences

本文介绍了一种优化的字符串匹配算法,通过预处理和哈希值计算来提高查询效率。该方法利用了字符串的本质不同长度特性,针对每个起点预处理哈希值,并使用Map存储答案,实现了高效查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

标签:根号算法

题目

题目传送门

Let us define a consistent set of occurrences of string t in string s as a set of occurrences of t in s such that no two occurrences intersect (in other words, no character position in s belongs to two different occurrences).

You are given a string s consisting of n lowercase English letters, and m queries. Each query contains a single string ti.

For each query, print the maximum size of a consistent set of occurrences of t in s.

Input

The first line contains two space-separated integers n and m: the length of string s and the number of queries (1 ≤ n ≤ 105, 1 ≤ m ≤ 105).

The second line contains the string s consisting of n lowercase English letters.

Each of the next m lines contains a single string ti consisting of lowercase English letters: the i-th query (1 ≤ |ti| ≤ n, where |ti| is the length of the string ti).

It is guaranteed that the total length of all ti does not exceed 105 characters.

Output

For each query i, print one integer on a separate line: the maximum size of a consistent set of occurrences of ti in s.

Example

Input

6 4
aaaaaa
a
aa
aaa
aaaa

Output

6
3
2
1

分析

显然,对于一个字符串S,考虑其中本质不同的长度只有 m m 个,所以我们对每个起点预处理出 m m 个hash值,然后将答案存入Map

之后对每个询问,排序后直接计算hash查询就好了

时间复杂度 O(nn) O ( n n )

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define mem(x,num) memset(x,num,sizeof x)
#define reg(x) for(int i=last[x];i;i=e[i].next)
using namespace std;
inline ll read(){
    ll f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//**********head by yjjr**********
#define pa pair <int,int>
#define mp make_pair
#define fi first
#define se second
const int maxn=1e5+6;
const int bas[2]={11257,12257};
const int Mod[2]={1e9+7,1e9+9};
int n,m,all,cur,l[maxn],r[maxn],ans[maxn],len[maxn],h[2][maxn],pwd[2][maxn];
map<pa,pa>cnt;
char s[maxn],t[maxn]; 
inline void solve(int len){
    cnt.clear();
    rep(i,len,n){
        pa val=mp((h[0][i]-1ll*h[0][i-len]*pwd[0][len]%Mod[0]+Mod[0])%Mod[0],(h[1][i]-1ll*h[1][i-len]*pwd[1][len]%Mod[1]+Mod[1])%Mod[1]);
        if(cnt.find(val)==cnt.end())cnt[val]=mp(1,i);
        else if(i-cnt[val].se<len)continue;else ++cnt[val].fi,cnt[val].se=i;
    }
    rep(i,1,m)
        if(r[i]-l[i]+1==len){
            pa cur=mp(0,0);
            rep(j,l[i],r[i])cur=mp((1ll*cur.fi*bas[0]+t[j])%Mod[0],(1ll*cur.se*bas[1]+t[j])%Mod[1]);
            ans[i]=cnt[cur].fi;
        }
}
int main(){
    n=read(),m=read();
    scanf("%s",s+1);
    pwd[0][0]=pwd[1][0]=1;
    rep(j,0,1)
        rep(i,1,n){
            h[j][i]=(1ll*h[j][i-1]*bas[j]+s[i])%Mod[j];
            pwd[j][i]=1ll*pwd[j][i-1]*bas[j]%Mod[j];
        }
    rep(i,1,m){
        scanf("%s",t+cur+1);
        l[i]=cur+1,len[i]=strlen(t+cur+1);
        cur+=len[i],r[i]=cur;
    }
    sort(len+1,len+1+m),all=unique(len+1,len+1+m)-len-1;
    rep(i,1,all)solve(len[i]);
    rep(i,1,m)printf("%d\n",ans[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值