阿轩在纸上写了两个字符串,分别记为A和B。
利用在数据结构与算法课上学到的知识,他很容易地求出了“字符串A从任意位置开始的后缀子串”与“字符串B”匹配的长度。
不过阿轩是一个勤学好问的同学,他向你提出了Q个问题:
在每个问题中,他给定你一个整数x,请你告诉他有多少个位置,满足“字符串A从该位置开始的后缀子串”与B匹配的长度恰好为x。
例如:A=aabcde,B=ab,则A有aabcde、abcde、bcde、cde、de、e这6个后缀子串,它们与B=ab的匹配长度分别是1、2、0、0、0、0。
因此A有4个位置与B的匹配长度恰好为0,有1个位置的匹配长度恰好为1,有1个位置的匹配长度恰好为2。
输入格式
第一行输入三个整数N,M,Q,分别表示A串长度、B串长度、问题个数。
第二行输入字符串A,第三行输入字符串B。
接下来Q行每行输入1个整数x,表示一个问题。
输出格式
输出共Q行,依次表示每个问题的答案。
数据范围
1≤N,M,Q,x≤2000001≤N,M,Q,x≤200000
输入样例:
6 2 5
aabcde
ab
0
1
2
3
4
输出样例:
4
1
1
0
0
题意:要你求原来的字符串的所有起点位置去匹配第二个字符串能匹配多少个字符,然后我们再输入x,看正好匹配长度为x的起点位置有多少个
思路:这个我们看能匹配多少个字符,这里其实匹配也就相当于相等,判断字符串相等自然用哈希,让我们我们又不知道他匹配的长度是多少,我们就需要枚举,既然可以枚举我们就可以优化成二分
求出两个字符串的哈希,然后预处理每个位置,二分长度用map存下来即可
#include<bits/stdc++.h> #define maxn 200005 #define mod 1000000007 using namespace std; typedef long long ll; typedef unsigned long long ull; ll n,m,q; char s1[maxn],s2[maxn]; ull dp1[maxn],dp2[maxn],f[maxn]; map<ll,ll> mp; void hash_code(){ f[0]=1; for(int i=1;i<=n;i++){ dp1[i]=dp1[i-1]*131+s1[i]-'a'+1; f[i]=f[i-1]*131; } for(int i=1;i<=m;i++){ dp2[i]=dp2[i-1]*131+s2[i]-'a'+1; } } int check(ll dex,ll len){ if(dp1[dex+len-1]-dp1[dex-1]*f[len]==dp2[len]){ return 1; } return 0; } int main(){ cin>>n>>m>>q; cin>>s1+1>>s2+1; hash_code(); for(ll i=1;i<=n;i++){ ll l=0,r=m+1,mn=0; while(l<r){ ll mid=(l+r)/2; if(check(i,mid)){ mn=mid; l=mid+1; } else{ r=mid; } } mp[mn]++; // cout<<mn<<" "; } int x; for(int i=0;i<q;i++){ cin>>x; cout<<mp[x]<<" "; } } /* 6 2 5 aabcde ab 0 1 2 3 4 5 */