hdu6230 Palindrome(Manacher + set + BIT)

版权声明:博主是菜鸡,但转的时候还是说一声吧 https://blog.csdn.net/qq_37666409/article/details/80555810

       

Palindrome

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 603    Accepted Submission(s): 234


Problem Description
Alice like strings, especially long strings. For each string, she has a special evaluation system to judge how elegant the string is. She defines that a string  S[1..3n2](n2) is one-and-half palindromic if and only if it satisfies  S[i]=S[2ni]=S[2n+i2](1in).For example,  abcbabc is one-and-half palindromic string, and  abccbaabc is not. Now, Alice has generated some long strings. She ask for your help to find how many substrings which is one-and-half palindromic.
 

Input
The first line is the number of test cases. For each test case, there is only one line containing a string(the length of strings is less than or equal to  500000), this string only consists of lowercase letters.
 

Output
For each test case, output a integer donating the number of one-and-half palindromic substrings.
 

Sample Input
 
  
1 ababcbabccbaabc
 

Sample Output
 
  
2
Hint
In the example input, there are two substrings which are one-and-half palindromic strings, $abab$ and $abcbabc$.
 

Source
 

        2017CCPC哈尔滨站A题……

        当时是全场AC率第三高的,然而英语水平有限,当时没有读懂题意,并没能AC,然而其实所谓的1.5回文串,就是一个回文串的回文中心被另一个回文串包含

        可能是我比较蠢,所以只想出了一个办法,先Manacher求出所有的回文串并记录它们的右边界,放到set里统计,如果右边界无法包含当前的位置就删除,同时用BIT统计之前的所有回文串位置,当set中删除时BIT中一并删除。

        居然跑了1700ms。。。慢的伤心。。。当时现场赛的时候,某个企业队好像用二分查找处理的字符串,生猛的一逼

        

#include <bits/stdc++.h>
#define lowbit(x) x & -x
#define LL long long

using namespace std;

const int MAXN = 500100;
const int INF = 0x7FFFFFFF;

template <typename T> inline void read(T &str) {
	int ch = getchar(), cnt = 0;
	while(ch > 'z' || ch < 'a') ch = getchar();
	str[0] = (char) ch, ch = getchar();
	while(ch <= 'z' && ch >= 'a') {
		str[++cnt] = (char) ch;
		ch = getchar();
	}
	return ;
}

struct node {
	int i, rs;
	node() {}
	node(int _i = 0, int _rs = 0) : i(_i), rs(_rs) {}
	
	bool operator < (const node & t) const {
		return rs < t.rs || (rs == t.rs && i < t.i);
	}
	
	bool operator == (const node & t) const {
		return (i == t.i) && (rs == t.rs);
	}
};

char s1[MAXN << 1], s2[MAXN << 1];
int p[MAXN << 1], bit[MAXN], r[MAXN];
int n, T;
int len1, len2;
set<node>s; 

void init() {
    len1 = n;
    s2[0] = '$';
    s2[1] = '#';
    for(int i = 0; i < len1; i++) {
        s2[2 * i + 2] = s1[i];
        s2[2 * i + 3] = '#';
    }
    len2 = len1 * 2 + 2;
    s2[len2] = '&';
}

void manacher() {
    int id = 0, mx = 0;
    for(int i = 1; i < len2; i++) {
        if(mx > i) p[i] = min(p[2 * id - i], mx - i);
        else p[i] = 1;
        while(s2[i + p[i]] == s2[i - p[i]]) p[i]++;
        if(i + p[i] > mx) {
            mx = i + p[i];
            id = i;
        }
    }
}

inline void update(int x, int y) {
	for(int i = x; i <= MAXN; i += lowbit(i)) bit[i] += y;
}

inline int query(int x) {
	int ret = 0;
	for(int i = x; i; i -= lowbit(i)) ret += bit[i];
	return ret;
}

inline void Clear() {
	memset(bit, 0, sizeof(bit));
	s.clear();
}

inline void _push(node c) {
	s.insert(c);
	update(c.i, 1);
}

inline void _delete(node c) {
	s.erase(c);
	update(c.i, -1);
}

signed main() {
	scanf("%d", &T);
	while(T --) {
		Clear();
		
		read(s1);
		n = (int) strlen(s1);
		
		init();
		manacher();
		
		for(int i = 1; i <= n; i++) {
			r[i] = (p[i * 2] - 1) >> 1;
		}
		
		LL ans = 0LL;
		for(int i = 1; i <= n; i++) {
			while(!s.empty() && s.begin()->rs < i) _delete(*s.begin());
			ans += query(i) - query(i - r[i] - 1);
			_push(node(i, i + r[i]));
		}
		
		printf("%lld\n", ans);
	}
	return 0;
}
如果谁有好的方法愿意告知,不胜感激

猜你喜欢

转载自blog.csdn.net/qq_37666409/article/details/80555810
BIT