Oulipo

题意:

查找一个字符串在另一个字符串中出现的次数.

Sample Input
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN
Sample Output
1
3
0

sol:字符hash或KMP。

程序代码1:字符hash,取mod。

 1 #include<bits/stdc++.h>
 2 #define maxn 1e6+10 
 3 using namespace std;
 4 const int mod=19260817;
 5 long long  p[1000001],sum[1000001],num;
 6 int n;
 7 int b=193;
 8 char c1[100001],c2[1000001];
 9 
10 int main()
11 {
12     p[0]=1;
13     for(int i=1;i<=maxn;i++)// 求出b^i 
14          p[i]=p[i-1]*b%mod;
15     cin>>n;
16     while(n--)
17     {
18         int ans=0;
19         num=0;
20         sum[0]=0;
21         scanf("%s %s",c1+1,c2+1);
22         //查找c1串在c2中出现的次数 
23         int len1=strlen(c1+1);
24         int len2=strlen(c2+1);
25         for(int i=1;i<=len1;i++)//计算c1串的hash值 
26              num=((num*b%mod)+(c1[i]-'A'+1))%mod;
27         for(int i=1;i<=len2;i++)//将c2串的前若干位的值计算出来 
28              sum[i]=((sum[i-1]*b%mod)+(c2[i]-'A'+1))%mod;
29         for(int i=0;i<=len2-len1;i++)
30         //从c2的第0位开始,依次取len1的长度出来,与c1进行比较 
31              if(num==((sum[i+len1]-sum[i]*p[len1]%mod)+mod)%mod)
32                ans++;
33         printf("%d
",ans);
34     }
35     return 0;
36 }

程序代码2:字符hash,利用无符号整数自然溢出取模

 1 #include<bits/stdc++.h>
 2 #define maxn 1e6+10
 3 using namespace std;
 4 typedef unsigned long long ull;
 5 ull p[1000001],sum[1000001],Num;
 6 int n;
 7 int b=193;
 8 char c1[100001],c2[1000001];
 9 void read(int &x)
10 {
11     char ch; bool ok;
12     for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
13     for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
14 }
15 int main()
16 {
17      
18     p[0]=1;
19     for(int i=1;i<=maxn;i++)
20          p[i]=p[i-1]*b;
21     read(n);
22     while(n--)
23     {
24         int ans=0;
25         Num=0;
26         sum[0]=0;
27         cin>>c1+1>>c2+1;
28         int len1=strlen(c1+1);
29         int len2=strlen(c2+1);
30         for(int i=1;i<=len1;i++)
31             Num=Num*b+ull(c1[i]-'A'+1);
32         for(int i=1;i<=len2;i++)
33             sum[i]=sum[i-1]*b+ull(c2[i]-'A'+1);
34         for(int i=0;i<=len2-len1;i++)
35              if(Num==sum[i+len1]-sum[i]*p[len1])
36                  ans++;
37         printf("%d
",ans);
38     }
39     return 0;
40 }

程序代码3:KMP

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 int pre[10010],t,n,m,ans;
 5 char a[10010],b[1000010];
 6  
 7 void get_next()
 8 {
 9     int j=0;
10     for (int i=1;i<n;i++)
11     {
12         while (j>0&&a[j+1]!=a[i+1]) j=pre[j];
13         if (a[j+1]==a[i+1]) j++;
14         pre[i+1]=j;
15     }
16 }
17  
18 void get_ans()
19 {
20     ans=0;
21     int j=0;
22     for (int i=0;i<m;i++)
23     {
24         while (j>0&&a[j+1]!=b[i+1]) j=pre[j];
25         if (a[j+1]==b[i+1]) j++;
26         if (j==n)
27         {
28             j=pre[j];//母串中的子串可重叠,j=pre[j]
//j=0;注意,如果母串中的子串不可重叠,j=0
29 ans++; 30 } 31 } 32 printf("%d ",ans); 33 } 34 35 int main(){ 36 scanf("%d",&t); 37 while (t--){ 38 memset(pre,0,sizeof(pre)); 39 scanf("%s",a+1); 40 n=strlen(a+1); 41 scanf("%s",b+1); 42 m=strlen(b+1); 43 get_next(); 44 get_ans(); 45 } 46 return 0; 47 }
原文地址:https://www.cnblogs.com/cutepota/p/12518087.html