無名(noname)
【问题描述】
因为是蒯的题所以没想好名字,为什么要用繁体呢?去看《唐诗三百首》吧!
题意很简单,给你一个串,求他有多少个不同的子串,满足前缀为A,后缀为B。
需要注意的是,串中所有的字母都是小写字母。
友情提示:如果你过不了样例,请注意是不同的子串。
【输入文件】
一共3行。
第一行母串S;
第二行串A;
第三行串B。
【输出文件】
一个数,即有多少不同的子串。
【输入样例】
abababab a b |
【输出样例】
4 |
【数据规模和约定】
100%:
length(S)<=2000;
length(A)<=2000;
length(B)<=2000;
30%:都少个0
字符串hash
首先,枚举每一个后缀是否前缀为A,front[i]表示i~l-1的前缀是否为A
同理处理出bside[i]表示0~i的后缀是否为B
枚举左右端点,可知当2个数组都为1才为一个解
但是解不能重复
于是用字符串hash,就是将字符串转数
hash[i]表示0~i的hash值
hash[i]=((hash[i-1]*p+idx(s[i]))%Mod
Mod和p都要慎重考虑,p取31,Mod取1e7+7
那么l~r的hash值为:hash(l~r)=(hash[r]-hash[l-1]*p^(r-l+1)+Mod)%Mod
一般Mod取1e9+7,但是这里要用bool数组,所以取1e7+7
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int p=31,Mod=100000007; 7 int l,la,lb,front[2001],bside[2001]; 8 char s[2001],A[2001],B[2001]; 9 long long pow[2001],hash[2001],ans; 10 bool vis[100000007]; 11 bool ask(int x,int y) 12 { 13 long long h=(hash[y]-(hash[x-1]*pow[y-x+1]%Mod)+Mod)%Mod; 14 if (vis[h]==0) 15 { 16 vis[h]=1; 17 return 1; 18 } 19 else 20 { 21 return 0; 22 } 23 } 24 int main() 25 {int i,j; 26 //freopen("noname.in","r",stdin); 27 //freopen("noname.out","w",stdout); 28 cin>>s; 29 cin>>A; 30 cin>>B; 31 l=strlen(s); 32 la=strlen(A); 33 lb=strlen(B); 34 for (i=0;i<l;i++) 35 { 36 for (j=1;j<=la,j+i-1<l;j++) 37 if (A[j-1]!=s[i+j-1]) break; 38 if (j>la) 39 front[i]=1; 40 } 41 for (i=l-1;i>=0;i--) 42 { 43 for (j=1;j<=lb,i-j+1>=0;j++) 44 if (B[lb-j]!=s[i-j+1]) break; 45 if (j>lb) 46 bside[i]=1; 47 } 48 hash[1]=(int)s[0]-96; 49 for (i=2;i<=l;i++) 50 { 51 hash[i]=(hash[i-1]*p+(int)s[i-1]-96)%Mod; 52 } 53 pow[0]=1; 54 for (i=1;i<=l;i++) 55 pow[i]=(pow[i-1]*p)%Mod; 56 for (i=0;i<l;i++) 57 { 58 for (j=i+max(la,lb)-1;j<l;j++) 59 if (front[i]&&bside[j]) 60 if (ask(i+1,j+1)) ans++; 61 } 62 cout<<ans; 63 }