您的位置:首页 > 其它

【POJ】1743 Musical Theme

2016-02-02 22:23 323 查看
后缀数组基础题目。
倍增法解。

/* 1743 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000")

#define sti                set<int>
#define stpii            set<pair<int, int> >
#define mpii            map<int,int>
#define vi                vector<int>
#define pii                pair<int,int>
#define vpii            vector<pair<int,int> >
#define rep(i, a, n)     for (int i=a;i<n;++i)
#define per(i, a, n)     for (int i=n-1;i>=a;--i)
#define clr                clear
#define pb                 push_back
#define mp                 make_pair
#define fir                first
#define sec                second
#define all(x)             (x).begin(),(x).end()
#define SZ(x)             ((int)(x).size())
#define lson            l, mid, rt<<1
#define rson            mid+1, r, rt<<1|1

const int maxn = 20005;
int a[maxn], b[maxn];
int rank[maxn], sa[maxn], height[maxn];
int wa[maxn], wb[maxn], wv[maxn], wc[maxn];
int n;

bool cmp(int *r, int a, int b, int l) {
return r[a]==r[b] && r[a+l]==r[b+l];
}

void da(int *r, int* sa, int n, int m) {
int i, j, p, *x=wa, *y=wb, *t;

for (i=0; i<m; ++i) wc[i] = 0;
for (i=0; i<n; ++i) wc[x[i]=r[i]]++;
for (i=1; i<m; ++i) wc[i] += wc[i-1];
for (i=n-1; i>=0; --i) sa[--wc[x[i]]] = i;
for (j=1,p=1; p<n; j*=2, m=p) {
for (p=0,i=n-j; i<n; ++i) y[p++] = i;
for (i=0; i<n; ++i) if (sa[i]>=j) y[p++] = sa[i]-j;
for (i=0; i<n; ++i) wv[i] = x[y[i]];
for (i=0; i<m; ++i) wc[i] = 0;
for (i=0; i<n; ++i) wc[wv[i]]++;
for (i=1; i<m; ++i) wc[i] += wc[i-1];
for (i=n-1; i>=0; --i) sa[--wc[wv[i]]] = y[i];
for (t=x, x=y, y=t, p=1, x[sa[0]]=0, i=1; i<n; ++i)
x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1:p++;
}
}

void calheight(int *r, int* sa, int n) {
int i, j, k = 0;

for (i=1; i<=n; ++i) rank[sa[i]] = i;
for (i=0; i<n; height[rank[i++]]=k)
for (k?k--:0, j=sa[rank[i]-1]; r[i+k]==r[j+k]; ++k) ;
}

void printSa(int n) {
puts("sa =");
rep(i, 1, n+1)
printf("%d ", sa[i]);
putchar('\n');
}

void printHeight(int n) {
puts("height =");
rep(i, 1, n+1)
printf("%d ", height[i]);
putchar('\n');
}

bool judge(int bound) {
int mx = INT_MIN, mn = INT_MAX;

rep(i, 1, n+1) {
if (height[i] >= bound) {
mx = max(mx, sa[i]);
mn = min(mn, sa[i]);
if (mx-mn >= bound)
return true;
} else {
mx = mn = sa[i];
}
}

return false;
}

void solve() {
rep(i, 0, n-1)
b[i] = a[i] - a[i+1] + 90;
b[n-1] = 0;
da(b, sa, n, 200);
calheight(b, sa, --n);

#ifndef ONLINE_JUDGE
// printSa(n);
// printHeight(n);
#endif

int l = 4, r = n, mid;
int ans = -1;

while (l <= r) {
mid = (l + r) >> 1;
if (judge(mid)) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}

printf("%d\n", ans+1);
}

int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif

while (scanf("%d", &n)!=EOF && n) {
rep(i, 0, n)
scanf("%d", &a[i]);
solve();
}

#ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif

return 0;
}


DC3解。

/* 1743 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000")

#define sti                set<int>
#define stpii            set<pair<int, int> >
#define mpii            map<int,int>
#define vi                vector<int>
#define pii                pair<int,int>
#define vpii            vector<pair<int,int> >
#define rep(i, a, n)     for (int i=a;i<n;++i)
#define per(i, a, n)     for (int i=n-1;i>=a;--i)
#define clr                clear
#define pb                 push_back
#define mp                 make_pair
#define fir                first
#define sec                second
#define all(x)             (x).begin(),(x).end()
#define SZ(x)             ((int)(x).size())
#define lson            l, mid, rt<<1
#define rson            mid+1, r, rt<<1|1

const int maxn = 20005;
int a[maxn], b[maxn*3];
int rank[maxn], sa[maxn*3], height[maxn];
int wa[maxn], wb[maxn], wv[maxn], wc[maxn];
int n;

bool c0(int *r, int a, int b) {
return r[a]==r[b] && r[a+1]==r[b+1] && r[a+2]==r[b+2];
}

bool c12(int k, int *r, int a, int b) {
if (k == 2)
return r[a]<r[b] || (r[a]==r[b] && c12(1, r, a+1, b+1));
else
return r[a]<r[b] || (r[a]==r[b] && wv[a+1]<wv[b+1]);
}

void sort(int *r, int *a, int *b, int n, int m) {
int i;

for (i=0; i<n; ++i) wv[i] = r[a[i]];
for (i=0; i<m; ++i) wc[i] = 0;
for (i=0; i<n; ++i) wc[wv[i]]++;
for (i=1; i<m; ++i) wc[i] += wc[i-1];
for (i=n-1; i>=0; --i) b[--wc[wv[i]]] = a[i];
}

#define F(x) ((x)/3 + ((x)%3==1 ? 0:tb))
#define G(x) ((x)<tb ? (x)*3+1 : ((x)-tb)*3+2)
void dc3(int *r, int* sa, int n, int m) {
int i, j, *rn = r + n, *san = sa + n;
int ta = 0, tb = (n + 1) / 3, tbc = 0, p;

r
= r[n+1] = 0;
for (i=0; i<n; ++i) if (i%3!=0) wa[tbc++] = i;
sort(r+2, wa, wb, tbc, m);
sort(r+1, wb, wa, tbc, m);
sort(r, wa, wb, tbc, m);
for (p=1, rn[F(wb[0])]=0, i=1; i<tbc; ++i)
rn[F(wb[i])] = c0(r, wb[i-1], wb[i]) ? p-1:p++;
if (p < tbc)
dc3(rn, san, tbc, p);
else
for (i=0; i<tbc; ++i) san[rn[i]] = i;
for (i=0; i<tbc; ++i)
if (san[i] < tb)
wb[ta++] = san[i] * 3;
if (n%3 == 1)
wb[ta++] = n-1;
sort(r, wb, wa, ta, m);
for (i=0; i<tbc; ++i) wv[wb[i]=G(san[i])]=i;
for (i=0,j=0,p=0; i<ta&&j<tbc; ++p)
sa[p] = c12(wb[j]%3, r, wa[i], wb[j]) ? wa[i++] : wb[j++];
while (i < ta) sa[p++] = wa[i++];
while (j < tbc) sa[p++] = wb[j++];
}

void calheight(int *r, int* sa, int n) {
int i, j, k = 0;

for (i=1; i<=n; ++i) rank[sa[i]] = i;
for (i=0; i<n; height[rank[i++]]=k)
for (k?k--:0, j=sa[rank[i]-1]; r[i+k]==r[j+k]; ++k) ;
}

void printSa(int n) {
puts("sa =");
rep(i, 1, n+1)
printf("%d ", sa[i]);
putchar('\n');
}

void printHeight(int n) {
puts("height =");
rep(i, 1, n+1)
printf("%d ", height[i]);
putchar('\n');
}

bool judge(int bound) {
int mx = INT_MIN, mn = INT_MAX;

rep(i, 1, n+1) {
if (height[i] >= bound) {
mx = max(mx, sa[i]);
mn = min(mn, sa[i]);
if (mx-mn >= bound)
return true;
} else {
mx = mn = sa[i];
}
}

return false;
}

void solve() {
rep(i, 0, n-1)
b[i] = a[i] - a[i+1] + 90;
b[n-1] = 0;
dc3(b, sa, n, 200);
calheight(b, sa, --n);

#ifndef ONLINE_JUDGE
printSa(n);
printHeight(n);
#endif

int l = 4, r = n, mid;
int ans = -1;

while (l <= r) {
mid = (l + r) >> 1;
if (judge(mid)) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}

printf("%d\n", ans+1);
}

int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif

while (scanf("%d", &n)!=EOF && n) {
rep(i, 0, n)
scanf("%d", &a[i]);
solve();
}

#ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif

return 0;
}


数据发生器。

from random import randint, shuffle
import shutil
import string

def GenDataIn():
with open("data.in", "w") as fout:
t = 20
bound = 88
for tt in xrange(t):
n = randint(1000, 5000)
fout.write("%d\n" % (n))
dataList = []
for i in xrange(n):
x = randint(1, bound)
dataList.append(x)
fout.write(" ".join(map(str, dataList)) + "\n")
fout.write("0\n")

def MovDataIn():
desFileName = "F:\eclipse_prj\workspace\hdoj\data.in"
shutil.copyfile("data.in", desFileName)

if __name__ == "__main__":
GenDataIn()
MovDataIn()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: