题意:
查找一个字符串在另一个字符串中出现的次数.
Sample Input
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN
Sample Output
1
3
0
Sol:典型的字符hash.
Std1:取mod
#include<bits/stdc++.h> #define maxn 1e6+10 using namespace std; const int mod=19260817; long long p[1000001],sum[1000001],num; int n; int b=193; char c1[100001],c2[1000001]; int main() { p[0]=1; for(int i=1;i<=maxn;i++)// 求出b^i p[i]=p[i-1]*b%mod; cin>>n; while(n--) { int ans=0; num=0; sum[0]=0; scanf("%s %s",c1+1,c2+1); //查找c1串在c2中出现的次数 int len1=strlen(c1+1); int len2=strlen(c2+1); for(int i=1;i<=len1;i++)//计算c1串的hash值 num=((num*b%mod)+(c1[i]-‘A‘+1))%mod; for(int i=1;i<=len2;i++)//将c2串的前若干位的值计算出来 sum[i]=((sum[i-1]*b%mod)+(c2[i]-‘A‘+1))%mod; for(int i=0;i<=len2-len1;i++) if(num==((sum[i+len1]-sum[i]*p[len1]%mod)+mod)%mod) ans++; printf("%d\n",ans); } return 0; }
Std2:用无符号整数计算hash值,用自然溢出求掉求模运算
#include<bits/stdc++.h> #define maxn 1e6+10 using namespace std; typedef unsigned long long ull; ull p[1000001],sum[1000001],Num; int n; int b=193; char c1[100001],c2[1000001]; void read(int &x) { char ch; bool ok; for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch==‘-‘) ok=1; for(x=0; isdigit(ch); x=x*10+ch-‘0‘,ch=getchar()); if(ok) x=-x; } int main() { p[0]=1; for(int i=1;i<=maxn;i++) p[i]=p[i-1]*b; read(n); while(n--) { int ans=0; Num=0; sum[0]=0; cin>>c1+1>>c2+1; int len1=strlen(c1+1); int len2=strlen(c2+1); for(int i=1;i<=len1;i++) Num=Num*b+ull(c1[i]-‘A‘+1); for(int i=1;i<=len2;i++) sum[i]=sum[i-1]*b+ull(c2[i]-‘A‘+1); for(int i=0;i<=len2-len1;i++) if(Num==sum[i+len1]-sum[i]*p[len1]) ans++; printf("%d\n",ans); } return 0; }
类似的习题有Poj2406 Power String,此题还可以用Kmp算法来做
#include<iostream> #include<cstdio> #include<string> #include<cstring> using namespace std; typedef unsigned long long LL; const LL base=131; const int N=1000010; int n; LL power[N],sum[N]; bool check(LL v,int k) //判断s[1]~s[k]是否是循环节 { for(register int i=1;i<=n;i+=k) //一路推过去每k位都应该值等于v { if(v!=sum[i+k-1]-sum[i-1]*power[k]) return 0; } return 1; } int main() { power[0]=1; for(register int i=1;i<=N-10;++i) //hash准备工作 power[i]=power[i-1]*base; char s[N]; while(scanf("%s",s+1)) { if(s[1]==‘.‘)break; n=strlen(s+1); sum[0]=0; for(register int i=1;i<=n;++i) sum[i]=sum[i-1]*base+LL(s[i]); for(register int i=1;i<=n;++i) { if(n%i) //循环节长度i,应为n的约数 continue; LL expect=sum[i]; if(check(expect,i)) { printf("%d\n",n/i); break; } } } return 0; }
原文:https://www.cnblogs.com/cutemush/p/12295936.html