题目链接: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 }