题目描述
这是一道模板题。
给定一个字符串 A 和一个字符串 B ,求 B 在 A 中的出现次数。A 和 B 中的字符均为英语大写字母或小写字母。
A 中不同位置出现的 B 可重叠。
输入格式
输入共两行,分别是字符串 A 和字符串 B 。
输出格式
输出一个整数,表示 B 在 A 中的出现次数。
样例
输入
zyzyzyz
zyz
输出
3
数据范围与提示
1 ≤ A , B 的长度 ≤ 1 0 6 , A 、 B 仅包含大小写字母。 1 \leq A, B 的长度 \leq 10 ^ 6 , A 、 B 仅包含大小写字母。 1≤A,B的长度≤106,A、B仅包含大小写字母。
模版题,证明略
#include
using namespace std;
const int x=17,M=1e7;
int a[M],b[M],h[M],ans=0;
char aa[M],bb[M];
int main(){
scanf("%s%s",aa+1,bb+1);
int m=strlen(aa+1),n=strlen(bb+1);
a[0]=1;
for (int i=1;i<=n;i++) a[i]=a[i-1]*x;
for (int i=1;i<=m;i++) h[i]=h[i-1]*x+aa[i]-'A'+1;
int s=0;
for (int i=1;i<=n;i++) s=s*x+(bb[i]-'A'+1);
for (int i=0;i<=m-n;i++)
if (s==h[i+n]-h[i]*a[n]) ans++;
cout<<ans;
return 0;
}
这里使用hash,这里给出递推式:
H ( C , i ) = H ( C , i − 1 ) ∗ x + c i ( c i = C i − ′ A ′ + 1 ) H(C,i)=H(C,i-1)*x+c_{i}\ (c_i=C_i-'A'+1) H(C,i)=H(C,i−1)∗x+ci (ci=Ci−′A′+1)
判断式:
H ( C ‘ ) = H ( C , i + n ) − H ( C , i ) ∗ x n H(C`)=H(C,i+n)-H(C,i)*x^n H(C‘)=H(C,i+n)−H(C,i)∗xn
至此得出原理.
scanf("%s%s",aa+1,bb+1);
int m=strlen(aa+1),n=strlen(bb+1);
指针原理,aa,bb是数组名,也是指针,strlen与scanf都与指针有关,可以使用指针运算读数.
a[0]=1;
for (int i=1;i<=n;i++) a[i]=a[i-1]*x;
递推计算幂,效率极高
当然,也可以对hash值取余,防止int溢出;
#include
using namespace std;
int main() {
string A, B;
cin >> A >> B;
int cnt = 0;
for (auto iter = A.begin(); iter <= A.end() - B.size(); iter++)
if (equal(B.begin(), B.end(), iter)) cnt++;
cout << cnt << endl;
return 0;
}
此方法仍可以过,效率相比较hash低下,但简单易懂:
我们首先输入字符串 A 和字符串 B。然后使用 equal函数在 A 中搜索 B 的出现位置,具体做法是遍历 A 的每个字符迭代器,判断以该位置为起点的子串是否与 B 相等,如果相等则计数器加一。
在以上代码中,我们将字符串 B 视为一个字符序列,以 A 中每个字符的迭代器为起点,调用 equal 函数判断与 B 是否相等。
综上所述,模版题,证明略