【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()

 

你可能感兴趣的:(【POJ】3415 Common Substrings)