CodeForces 113B Petr#

题目链接:http://codeforces.com/problemset/problem/113/B

题目大意:

多组数据
每组给定3个字符串T,Sbeg,Sed,求字符串T中有多少子串是以Sbeg开头,Sed结尾的

分析:

  难点在哈希函数的编写,如果直接存string会爆内存,不能用STL自带哈希函数,用了会Wa。

代码如下:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3  
  4 #define rep(i,n) for (int i = 0; i < (n); ++i)
  5 #define For(i,s,t) for (int i = (s); i <= (t); ++i)
  6 #define rFor(i,t,s) for (int i = (t); i >= (s); --i)
  7 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
  8 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i)
  9  
 10 #define pr(x) cout << #x << " = " << x << "  "
 11 #define prln(x) cout << #x << " = " << x << endl
 12  
 13 #define ALL(x) x.begin(),x.end()
 14 #define INS(x) inserter(x,x.begin())
 15  
 16 #define ms0(a) memset(a,0,sizeof(a))
 17 #define msI(a) memset(a,inf,sizeof(a))
 18  
 19 #define pii pair<int,int> 
 20 #define piii pair<pair<int,int>,int> 
 21 #define mp make_pair
 22 #define pb push_back
 23 #define fi first
 24 #define se second
 25  
 26 inline int gc(){
 27     static const int BUF = 1e7;
 28     static char buf[BUF], *bg = buf + BUF, *ed = bg;
 29      
 30     if(bg == ed) fread(bg = buf, 1, BUF, stdin);
 31     return *bg++;
 32 } 
 33  
 34 inline int ri(){
 35     int x = 0, f = 1, c = gc();
 36     for(; c<48||c>57; f = c=='-'?-1:f, c=gc());
 37     for(; c>47&&c<58; x = x*10 + c - 48, c=gc());
 38     return x*f;
 39 }
 40  
 41 typedef long long LL;
 42 typedef unsigned long long uLL;
 43 const LL mod = 1e9 + 7;
 44 const int maxN = 2000 + 7;
 45  
 46 string T, Sbeg, Sed;
 47 unordered_set< LL > sll;
 48 int beg[maxN], begLen; // 记录 Sbeg出现的位置 
 49 int ed[maxN], edLen; // 记录 Sed出现的位置 
 50  
 51 // h为T的后缀哈希数组 
 52 // h[i]表示T从i位置开始的后缀的哈希值 
 53 // h[i] = T[i] + T[i+1]*key + T[i+2]*key^2 + ……+ T[i+len-1-i]*key^len-1-i
 54 // xp为基数数组
 55 // xp[i] = key^i
 56 LL xp[maxN], h[maxN];
 57 const LL key = 1e9 + 7;
 58  
 59 // 求起点为s,长为len的子串的哈希值 
 60 // Hash(i, len) = T[i] + T[i+1]*key + T[i+2]*key^2 + ……+ T[i+len-1]*key^len-1
 61 LL Hash(int s, int len) {
 62     return h[s] - h[s + len] * xp[len];
 63 }
 64   
 65 void HashInit(const char* s, LL* h, int len) {
 66     xp[0] = 1;
 67     For(i, 1, maxN - 1) xp[i] = xp[i - 1] * key;
 68          
 69     h[len] = 0;
 70     rFor(i, len - 1, 0) h[i] = h[i + 1] * key + s[i];        
 71 }
 72  
 73 int main(){
 74     while(cin >> T >> Sbeg >> Sed) {
 75         HashInit(T.c_str(), h, (int)T.size());
 76          
 77         int ans = 0;
 78         sll.clear();
 79         begLen = edLen = 0;
 80          
 81         int p = 0;
 82         while(p < T.size()) {
 83             int t = T.find(Sbeg.c_str(), p);
 84             if(t == string::npos) break;
 85             beg[begLen++] = t;
 86             p = t + 1;
 87         }
 88          
 89         p = 0;
 90         while(p < T.size()) {
 91             int t = T.find(Sed.c_str(), p);
 92             if(t == string::npos) break;
 93             ed[edLen++] = t;
 94             p = t + 1;
 95         }
 96          
 97         int i = 0, j = 0;
 98         while(i < begLen && j < edLen) {
 99             if(beg[i] <= ed[j]) {
100                 For(k, j, edLen - 1) {
101                     if(beg[i] + Sbeg.size() > ed[k] + Sed.size()) continue;
102                     sll.insert(Hash(beg[i], ed[k] + Sed.size() - beg[i]));
103                 }
104                 ++i;
105             }
106             else ++j;
107         }
108          
109         cout << sll.size() << endl;
110     }
111     return 0;
112 }
View Code

猜你喜欢

转载自www.cnblogs.com/zaq19970105/p/10733044.html