XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Saratov. K. Consistent Occurrences 哈希

Problem K. Consistent Occurrences

Input file: standard input
Output file: standard output
Time limit: 8 seconds
Memory limit: 256 mebibytes

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 ≤ jtij ≤ n, where jtij 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.

Sample InputSample Output
6 4
aaaaaa
a
aa
aaa
aaaa
6 3 2 1


多次查询某个字符串在原串最多不重叠的交叉多少次。

使用字符串哈希,离线操作,每次对原串所有长度一样的子串进行查询操作。由于最多只有 n n 种长度,所以复杂度降为 O(nn) O ( n n ) .

需要注意,使用map时如果直接查询,map的size会不断增大。此时,必须使用count()或者find()查询。

#include <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#define pb push_back 
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
typedef pair<ll,int> pp;
const int maxn=100005;
const ll llinf=0x3f3f3f3f3f3f3f3f,seed=512467,mod=1e9+7;
const ld pi=acos(-1.0L);
ll fac[maxn],hs[maxn],hsh[maxn];
int len[maxn];
pp hn[maxn];
bool lz[maxn];
map<ll,int> ans,mp;
char s[maxn],t[maxn];

ll hash(int n) {
    fac[0]=1;hsh[0]=0;
    for (int i=1;i<=n;i++) {
        fac[i]=(fac[i-1]*seed)%mod;
        hsh[i]=hsh[i-1]*seed%mod+s[i];
        hsh[i]%=mod;
    }
}

int main() {
    int n,m;
    scanf("%d%d",&n,&m);
    scanf("%s",s+1);
    hash(n);
    for (int i=1;i<=m;i++) {
        scanf("%s",t+1);
        len[i]=strlen(t+1);
        hs[i]=0;
        lz[len[i]]=1;
        for (int j=1;j<=len[i];j++) {
            hs[i]=(hs[i]*seed+t[j])%mod;
        }
        mp[hs[i]]=1;
    }
    for (int i=1;i<=n;i++) {
        if (!lz[i]) continue;
        for (int j=1;j+i-1<=n;j++) {
            hn[j]=pp((hsh[j+i-1]-hsh[j-1]*fac[i]%mod+mod)%mod,j);
        }
        sort(hn+1,hn+n-i+2);
        for (int j=1;j+i-1<=n;) {
            int k=j,cnt=1;
            while (hn[k+1].first==hn[j].first&&k+i<=n) k++;
            if (!mp.count(hn[j].first)) {
                j=k+1;continue;
            }
            int last=hn[j].second;
            for (int l=j+1;l<=k;l++) {
                if (hn[l].second-last>=i) cnt++,last=hn[l].second;
            }
            ans[hn[j].first]=cnt;
            j=k+1;
        }
    }
    for (int i=1;i<=m;i++) {
        printf("%d\n",ans[hs[i]]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值