【POJ】3415 Common Substrings
后缀数组可解。使用单调栈优化。
1 /* 3415 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <algorithm> 12 #include <cstdio> 13 #include <cmath> 14 #include <ctime> 15 #include <cstring> 16 #include <climits> 17 #include <cctype> 18 #include <cassert> 19 #include <functional> 20 #include <iterator> 21 #include <iomanip> 22 using namespace std; 23 //#pragma comment(linker,"/STACK:102400000,1024000") 24 25 #define sti set<int> 26 #define stpii set<pair<int, int> > 27 #define mpii map<int,int> 28 #define vi vector<int> 29 #define pii pair<int,int> 30 #define vpii vector<pair<int,int> > 31 #define rep(i, a, n) for (int i=a;i<n;++i) 32 #define per(i, a, n) for (int i=n-1;i>=a;--i) 33 #define clr clear 34 #define pb push_back 35 #define mp make_pair 36 #define fir first 37 #define sec second 38 #define all(x) (x).begin(),(x).end() 39 #define SZ(x) ((int)(x).size()) 40 #define lson l, mid, rt<<1 41 #define rson mid+1, r, rt<<1|1 42 43 const int maxl = 1e5+5; 44 const int maxn = maxl * 2; 45 char as[maxl], bs[maxl]; 46 int a[maxn]; 47 int rank[maxn], height[maxn], sa[maxn]; 48 int wa[maxn], wb[maxn], wc[maxn], wv[maxn]; 49 int S[maxn][2]; 50 int K; 51 52 bool cmp(int *r, int a, int b, int l) { 53 return r[a]==r[b] && r[a+l]==r[b+l]; 54 } 55 56 void da(int *r, int *sa, int n, int m) { 57 int i, j, *x=wa, *y=wb, *t, p; 58 59 for (i=0; i<m; ++i) wc[i] = 0; 60 for (i=0; i<n; ++i) wc[x[i]=r[i]]++; 61 for (i=1; i<m; ++i) wc[i] += wc[i-1]; 62 for (i=n-1; i>=0; --i) sa[--wc[x[i]]] = i; 63 for (j=1,p=1; p<n; j*=2, m=p) { 64 for (p=0,i=n-j; i<n; ++i) y[p++] = i; 65 for (i=0; i<n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j; 66 for (i=0; i<n; ++i) wv[i] = x[y[i]]; 67 for (i=0; i<m; ++i) wc[i] = 0; 68 for (i=0; i<n; ++i) wc[wv[i]]++; 69 for (i=1; i<m; ++i) wc[i] += wc[i-1]; 70 for (i=n-1; i>=0; --i) sa[--wc[wv[i]]] = y[i]; 71 for (t=x,x=y,y=t, x[sa[0]]=0, p=1, i=1; i<n; ++i) 72 x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1:p++; 73 } 74 } 75 76 void calheight(int *r, int *sa, int n) { 77 int i, j, k = 0; 78 79 for (i=1; i<=n; ++i) rank[sa[i]] = i; 80 for (i=0; i<n; height[rank[i++]]=k) 81 for (k?k--:0, j=sa[rank[i]-1]; r[i+k]==r[j+k]; ++k); 82 } 83 84 void printSa(int n) { 85 for (int i=1; i<=n; ++i) 86 printf("%d ", sa[i]); 87 putchar('\n'); 88 } 89 90 void printHeight(int n) { 91 for (int i=1; i<=n; ++i) 92 printf("%d ", height[i]); 93 putchar('\n'); 94 } 95 96 void solve() { 97 int n = 0, nn; 98 99 for (int i=0; ; ++i) { 100 if (as[i] == '\0') { 101 nn = i; 102 break; 103 } 104 a[n++] = as[i]; 105 } 106 a[n++] = 1; 107 for (int i=0; ; ++i) { 108 if (bs[i] == '\0') { 109 break; 110 } 111 a[n++] = bs[i]; 112 } 113 a[n] = 0; 114 115 da(a, sa, n+1, 130); 116 calheight(a, sa, n); 117 118 int top; 119 __int64 tot, ans = 0; 120 121 // handle as with bs 122 top = 0; 123 tot = 0; 124 rep(i, 1, n+1) { 125 if (height[i] < K) { 126 top = 0; 127 tot = 0; 128 } else { 129 int cnt = 0; 130 if (sa[i-1] < nn) { 131 ++cnt; 132 tot += height[i] - K + 1; 133 } 134 while (top && height[i]<=S[top-1][0]) { 135 --top; 136 tot -= 1LL * S[top][1] * (S[top][0] - height[i]); 137 cnt += S[top][1]; 138 } 139 S[top][0] = height[i]; 140 S[top][1] = cnt; 141 ++top; 142 if (sa[i] > nn) 143 ans += tot; 144 } 145 } 146 147 148 tot = 0; 149 top = 0; 150 rep(i, 1, n+1) { 151 if (height[i] < K) { 152 tot = 0; 153 top = 0; 154 } else { 155 int cnt = 0; 156 if (sa[i-1] > nn) { 157 ++cnt; 158 tot += height[i] - K + 1; 159 } 160 while (top && height[i]<=S[top-1][0]) { 161 --top; 162 tot -= 1LL * S[top][1] * (S[top][0] - height[i]); 163 cnt += S[top][1]; 164 } 165 S[top][0] = height[i]; 166 S[top][1] = cnt; 167 ++top; 168 if (sa[i] < nn) 169 ans += tot; 170 } 171 } 172 173 printf("%I64d\n", ans); 174 } 175 176 int main() { 177 ios::sync_with_stdio(false); 178 #ifndef ONLINE_JUDGE 179 freopen("data.in", "r", stdin); 180 freopen("data.out", "w", stdout); 181 #endif 182 183 while (scanf("%d", &K)!=EOF && K) { 184 scanf("%s%s", as, bs); 185 solve(); 186 } 187 188 #ifndef ONLINE_JUDGE 189 printf("time = %d.\n", (int)clock()); 190 #endif 191 192 return 0; 193 }
数据发生器。
1 from random import randint, shuffle 2 import shutil 3 import string 4 5 6 def GenDataIn(): 7 with open("data.in", "w") as fout: 8 t = 20 9 bound = 10**2 10 lc = list(string.lowercase) 11 for tt in xrange(t): 12 k = randint(1, 10) 13 fout.write("%d\n" % (k)) 14 length = randint(100, 500) 15 line = "" 16 for i in xrange(length): 17 idx = randint(0, 25) 18 line += lc[idx] 19 fout.write("%s\n" % line) 20 length = randint(100, 500) 21 line = "" 22 for i in xrange(length): 23 idx = randint(0, 25) 24 line += lc[idx] 25 fout.write("%s\n" % line) 26 fout.write("0\n") 27 28 29 def MovDataIn(): 30 desFileName = "F:\eclipse_prj\workspace\hdoj\data.in" 31 shutil.copyfile("data.in", desFileName) 32 33 34 if __name__ == "__main__": 35 GenDataIn() 36 MovDataIn()