답안 #259067

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
259067 2020-08-07T06:40:42 Z pure_mem 회문 (APIO14_palindrome) C++14
73 / 100
1000 ms 55268 KB
#include <bits/stdc++.h>
 
#define ll long long
#define X first
#define Y second
#define MP make_pair
 
using namespace std;
 
const int N = 3e5 + 3;
 
struct sarr{
	ll mod1 = 1e9 + 7, mod2 = 1e9 + 9, mod3 = 1e9 + 21;
	ll pr1[N], pr2[N], pr3[N];
	ll hs1[N], hs2[N], hs3[N], rhs1[N], rhs2[N], rhs3[N];
	int sf[N], poses[N], lcm[N], sp[19][N], lg[N];
	string s;
 
	unordered_map< ll, bool > were;
 
	void init(string temp){
		s = temp;
		pr1[0] = pr2[0] = pr3[0] = 1;
		lg[1] = 0;
		for(int i = 1;i < N;i++){
			pr1[i] = pr1[i - 1] * 29 % mod1;
			pr2[i] = pr2[i - 1] * 31 % mod2;
		//	pr3[i] = pr3[i - 1] * 37 % mod3;
			if(i > 1)
				lg[i] = lg[i / 2] + 1;
		}
		for(int i = 0;i < (int)temp.size();i++){
			sf[i + 1] = i + 1;
			hs1[i + 1] = (hs1[i] + (temp[i] - 'a' + 1) * pr1[i]) % mod1;
			hs2[i + 1] = (hs2[i] + (temp[i] - 'a' + 1) * pr2[i]) % mod2;
		//	hs3[i + 1] = (hs3[i] + (temp[i] - 'a' + 1) * pr3[i]) % mod3;	
		}
		for(int i = 0;i < (int)temp.size();i++){
			int j = (int)temp.size() - i - 1;
			rhs1[j + 1] = (rhs1[j + 2] + (temp[j] - 'a' + 1) * pr1[i]) % mod1;
			rhs2[j + 1] = (rhs2[j + 2] + (temp[j] - 'a' + 1) * pr2[i]) % mod2;
	//		rhs3[j + 1] = (rhs3[j + 2] + (temp[j] - 'a' + 1) * pr3[i]) % mod3;	
		}
		this->build_sf();
		for(int i = 1;i < (int)temp.size();i++){
			lcm[i] = this->get_lcm(sf[i], sf[i + 1]);
		//	cerr << lcm[i] << " ";
		}
		//cerr << endl;
		for(int i = 1;i <= (int)temp.size();i++){
			sp[0][i] = lcm[i];
		//	cerr << sf[i] << " ";
			poses[sf[i]] = i;
		}
		for(int i = 1;i < 19;i++){
			for(int j = 1;j + (1 << i) - 1 <= (int)temp.size();j++){
				sp[i][j] = min(sp[i - 1][j], sp[i - 1][j + (1 << (i - 1))]);
			}
		}
	}

	void build_sf(){
		string temp = s;
		temp += "#"; 
		int n = temp.size();
		vector<int> cl(n, 0), pn(n, 0), cn(n, 0), p(n, 0), cnt(n, 0);
		for(int i = 0;i < n;i++)
			p[i] = i;
		sort(p.begin(), p.end(), [this](int x, int y){
			if(s[x] < s[y])
				return 1;
			return 0;
		});
		int classes = 0;
		for(int i = 1;i < n;i++){
			if(s[p[i]] != s[p[i - 1]])
				classes++;
			cl[p[i]] = classes;
		}
		for(int it = 0;(1 << it) < n;it++){
			for(int i = 0;i < n;i++){
				pn[i] = p[i] - (1 << it);
				if(pn[i] < 0)
					pn[i] += n;
			}
			memset(&cnt[0], 0, sizeof(cnt[0]) * cnt.size());
		//	memset(cnt, 0, sizeof(cnt));
			//cnt.assign(cnt.size(), 0);
			for(int i = 0;i < n;i++){
				++cnt[cl[pn[i]]];
			}
			for(int i = 1;i <= classes;i++){
				cnt[i] += cnt[i - 1];	
			}
			for(int i = n - 1;i >= 0;i--){
				p[--cnt[cl[pn[i]]]] = pn[i];
			}
			cn[p[0]] = 0;
			classes = 0;
			for(int i = 1;i < n;i++){
				int m1 = (p[i] + (1 << it)) % n, m2 = (p[i - 1] + (1 << it)) % n;
				if(cl[p[i]] != cl[p[i - 1]] || cl[m1] != cl[m2])
					classes++;
				cn[p[i]] = classes;
			}
			cl.swap(cn);
			//for(int i = 0;i < n;i++)
			//	cl[i] = cn[i];
		}
		for(int i = 2;i <= n;i++){
			sf[i - 1] = p[i - 1] + 1;	
		}
	}
 
	bool check(int l, int r){
		bool can = 1;
	//	return can;
		ll add1 = 0, add2 = 0;
		if(l > (int)s.size() - r + 1)
			add2 = l - ((int)s.size() - r + 1);
		else
			add1 = (int)s.size() - r + 1 - l;
		if((hs1[r] - hs1[l - 1] + mod1) % mod1 * pr1[add1] % mod1 != (rhs1[l] - rhs1[r + 1] + mod1) % mod1 * pr1[add2] % mod1)
			can = 0;
		if((hs2[r] - hs2[l - 1] + mod2) % mod2 * pr2[add1] % mod2 != (rhs2[l] - rhs2[r + 1] + mod2) % mod2 * pr2[add2] % mod2)
			can = 0;
		//if((hs3[r] - hs3[l - 1] + mod3) % mod3 * pr3[add1] % mod3 != (rhs3[l] - rhs3[r + 1] + mod3) % mod3 * pr3[add2] % mod3)
		//	can = 0;
		return can;
	}
 
	bool check_eq(int l1, int r1, int l2, int r2){
		bool can = 1;
		if(l1 > l2)
			swap(l1, l2), swap(r1, r2);
		if(((hs1[r1] - hs1[l1 - 1] + mod1) % mod1) * pr1[l2 - l1] % mod1 != (hs1[r2] - hs1[l2 - 1] + mod1) % mod1)
			can = 0;
		if(((hs2[r1] - hs2[l1 - 1] + mod2) % mod2) * pr2[l2 - l1] % mod2 != (hs2[r2] - hs2[l2 - 1] + mod2) % mod2)
			can = 0;
		//if(((hs3[r1] - hs3[l1 - 1] + mod3) % mod3) * pr3[l2 - l1] % mod3 != (hs3[r2] - hs3[l2 - 1] + mod3) % mod3)
		//	can = 0;
		return can;
	}
 
	int get_lcm(int l, int r){
		if(l > r)
			swap(l, r);
		int tl = 1, tr = (int)s.size() - r + 1, tp = 0;
		while(tl <= tr){
			int tm = (tl + tr) / 2;
			if(this->check_eq(l, l + tm - 1, r, r + tm - 1))
				tl = tm + 1, tp = tm;
			else
				tr = tm - 1;
		}
		return tp;
	}
 
	bool is_less(int l, int r){
		int lc = this->get_lcm(l, r);
		if(l + lc - 1 == (int)s.size())
			return 1;
		else if(r + lc - 1 == (int)s.size())
			return 0;
		return s[l + lc - 1] < s[r + lc - 1];
	}
 
	bool is_were(int l, int r){
		ll hash1 = ((hs1[r] - hs1[l - 1] + mod1) % mod1) * pr1[(int)s.size() - l] % mod1;
		ll hash2 = ((hs2[r] - hs2[l - 1] + mod2) % mod2) * pr2[(int)s.size() - l] % mod2;
		hash1 = hash1 + hash2 * mod3;
		//ll hash3 = ((hs3[r] - hs3[l - 1] + mod3) % mod3) * pr3[(int)s.size() - l] % mod3;
		if(were.count(hash1))
			return 0;
		were[hash1] = 1;
		return 1;
	}
 
	int lcm_min(int l, int r){
		if(l == r)
			return (int)s.size() - l + 1;
		r -= 1;
		int lens = (r - l + 1);
		//cerr << lg[lens] << " " << lens << " " << sp[lg[lens]][l] << "s\n";
		return min(sp[lg[lens]][l], sp[lg[lens]][r - (1 << lg[lens]) + 1]);	
	}
 
	int get_cnt(int l, int r){
		int idx = poses[l];
		int tl = 1, tr = idx - 1, res = 1;
		while(tl <= tr){
			int tm = (tl + tr) / 2;
			if(this->lcm_min(tm, idx) >= r - l + 1){
				tr = tm - 1, res = idx - tm + 1;
			}
			else{
				tl = tm + 1;
			}
		}
		int tp = 1;
		tl = idx + 1, tr = (int)s.size();
		while(tl <= tr){
			int tm = (tl + tr) / 2;
			if(this->lcm_min(idx, tm) >= r - l + 1){
				tl = tm + 1, tp = tm - idx + 1;
			}
			else{
				tr = tm - 1;
			}
		}
	//	cerr << res << " " << tp << "\n";
		return res + tp - 1;
	}
}g;

int d1[N], d2[N];

void manachar(){
 	int l = 0, r = -1;
 	int n = g.s.size();
 	for(int i = 0;i < n;i++){
 		int k = (i > r ? 1: min(d1[l + r - i], r - i + 1));
 		while(k + i < n && i - k >= 0 && g.s[i + k] == g.s[i - k])k++;
 		d1[i] = k;
 		if(i + k - 1 > r)
 			l = i - k + 1, r = i + k - 1;
 	}
 	l = 0, r = -1;
 	for(int i = 0;i < n;i++){
 		int k = (i > r ? 0: min(d1[l + r - i + 1], r - i + 1));
 		while(k + i < n && i - k - 1 >= 0 && g.s[i + k] == g.s[i - k - 1])k++;
 		d2[i] = k;
 		if(i + k - 1 > r)
 			l = i - k, r = i + k - 1;
 	}

}
 
int main () {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
 
    //double start_f = clock();

    cin >> g.s;
    //cerr << g.s << "\n";
    ll res = 0;
    g.init(g.s);
    manachar();
    int n = g.s.size();
   // cerr << g.check(26, 27) << " " << g.s[25] << " " << g.s[26]<< "\n";
    for(int mid = 1;mid <= n;mid++){
    	int tp = d1[mid - 1] - 1;
    //	cerr << mid << " " << tp << "\n";
    	for(int l = mid - tp, r = mid + tp; l <= r;l++, r--){
    	//	cerr << "was " << " " << l << " " << r << "\n";
    		if(!g.is_were(l, r))
    			break;
    		//break; // UBRAT ------------------------------------------------
    	//	cerr << "was\n";
    	//	cerr << l << " " << r << " " << g.get_cnt(l, r) << "\n";
    		res = max(res, (r - l + 1ll) * g.get_cnt(l, r));
    	}
    }
    //cerr << g.get_cnt(5, 6) << "\n";
    for(int mid = 2;mid <= n;mid++){
    	if(g.s[mid - 1] != g.s[mid - 2])
    		continue;
    	int tp = d2[mid - 1];
    	for(int l = mid - tp, r = mid + tp - 1; l <= r;l++, r--){
    		if(!g.is_were(l, r))
    			break;
    	//	cerr << l << " " << r << " " << g.get_cnt(l, r) << "\n";
    		res = max(res, (r - l + 1ll) * g.get_cnt(l, r));
    	}
    }
    cout << res;

    //cerr << (clock() - start_f) / CLOCKS_PER_SEC;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 7 ms 6272 KB Output is correct
2 Correct 8 ms 6272 KB Output is correct
3 Correct 7 ms 6272 KB Output is correct
4 Correct 7 ms 6272 KB Output is correct
5 Correct 7 ms 6272 KB Output is correct
6 Correct 8 ms 6272 KB Output is correct
7 Correct 7 ms 6272 KB Output is correct
8 Correct 7 ms 6272 KB Output is correct
9 Correct 8 ms 6272 KB Output is correct
10 Correct 7 ms 6272 KB Output is correct
11 Correct 7 ms 6272 KB Output is correct
12 Correct 7 ms 6272 KB Output is correct
13 Correct 7 ms 6272 KB Output is correct
14 Correct 7 ms 6272 KB Output is correct
15 Correct 8 ms 6272 KB Output is correct
16 Correct 7 ms 6272 KB Output is correct
17 Correct 7 ms 6272 KB Output is correct
18 Correct 7 ms 6272 KB Output is correct
19 Correct 7 ms 6272 KB Output is correct
20 Correct 8 ms 6272 KB Output is correct
21 Correct 7 ms 6272 KB Output is correct
22 Correct 7 ms 6272 KB Output is correct
23 Correct 7 ms 6272 KB Output is correct
24 Correct 7 ms 6272 KB Output is correct
25 Correct 7 ms 6272 KB Output is correct
26 Correct 7 ms 6272 KB Output is correct
27 Correct 7 ms 6272 KB Output is correct
28 Correct 7 ms 6272 KB Output is correct
29 Correct 7 ms 6272 KB Output is correct
30 Correct 7 ms 6272 KB Output is correct
31 Correct 7 ms 6272 KB Output is correct
32 Correct 7 ms 6272 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 8 ms 6400 KB Output is correct
2 Correct 8 ms 6400 KB Output is correct
3 Correct 8 ms 6400 KB Output is correct
4 Correct 8 ms 6400 KB Output is correct
5 Correct 8 ms 6528 KB Output is correct
6 Correct 9 ms 6528 KB Output is correct
7 Correct 8 ms 6528 KB Output is correct
8 Correct 8 ms 6528 KB Output is correct
9 Correct 8 ms 6400 KB Output is correct
10 Correct 8 ms 6400 KB Output is correct
11 Correct 9 ms 6400 KB Output is correct
12 Correct 8 ms 6400 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 20 ms 7828 KB Output is correct
2 Correct 19 ms 7828 KB Output is correct
3 Correct 20 ms 7828 KB Output is correct
4 Correct 20 ms 7828 KB Output is correct
5 Correct 21 ms 7828 KB Output is correct
6 Correct 21 ms 7828 KB Output is correct
7 Correct 19 ms 7828 KB Output is correct
8 Correct 16 ms 7452 KB Output is correct
9 Correct 16 ms 7444 KB Output is correct
10 Correct 21 ms 7700 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 173 ms 21732 KB Output is correct
2 Correct 159 ms 21692 KB Output is correct
3 Correct 170 ms 21688 KB Output is correct
4 Correct 176 ms 21692 KB Output is correct
5 Correct 251 ms 21692 KB Output is correct
6 Correct 194 ms 20800 KB Output is correct
7 Correct 192 ms 21180 KB Output is correct
8 Correct 138 ms 17900 KB Output is correct
9 Correct 141 ms 18652 KB Output is correct
10 Correct 345 ms 21180 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 628 ms 55016 KB Output is correct
2 Correct 597 ms 55268 KB Output is correct
3 Correct 645 ms 55224 KB Output is correct
4 Correct 580 ms 55184 KB Output is correct
5 Execution timed out 1103 ms 54424 KB Time limit exceeded
6 Halted 0 ms 0 KB -