HDU 3948 The Number of Palindromes

原创 2016年08月28日 17:20:53

Description

Now, you are given a string S. We want to know how many distinct substring of S which is palindrome.

Input

The first line of the input contains a single integer T(T<=20), which indicates number of test cases. 
Each test case consists of a string S, whose length is less than 100000 and only contains lowercase letters. 

Output

For every test case, you should output "Case #k:" first in a single line, where k indicates the case number and starts at 1. Then output the number of distinct substring of S which is palindrome. 

Sample Input

3
aaaa
abab
abcd

Sample Output

Case #1: 4
Case #2: 4

Case #3: 4

求本质不同的回文子串的数目,显然是用回文树搞定最轻松了,这里为了是练习后缀数组。

#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
#define loop(i,j,k) for (int i = j;i != -1; i = k[i])
#define lson x << 1, l, mid
#define rson x << 1 | 1, mid + 1, r
#define fi first
#define se second
#define mp(i,j) make_pair(i,j)
#define pii pair<string,string>
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const double eps = 1e-8;
const int INF = 0x7FFFFFFF;
const int mod = 1e8;
const int N = 5e5 + 10;
const int read()
{
	char ch = getchar();
	while (ch<'0' || ch>'9') ch = getchar();
	int x = ch - '0';
	while ((ch = getchar()) >= '0'&&ch <= '9') x = x * 10 + ch - '0';
	return x;
}
int T, cas = 0;

struct Sa
{
	char s[N];
	int rk[2][N], sa[N], h[N], w[N], now, n;
	int rmq[N][20], lg[N];

	bool GetS()
	{
		scanf("%s", s + 1);
		n = strlen(s + 1); 
		s[n + 1] = 2;
		rep(i, 1, n) s[n + n + 2 - i] = s[i];
		n = n + n + 1;
		return true;
	}

	void getsa(int z, int &m)
	{
		int x = now, y = now ^= 1;
		rep(i, 1, z) rk[y][i] = n - i + 1;
		for (int i = 1, j = z; i <= n; i++)
			if (sa[i] > z) rk[y][++j] = sa[i] - z;

		rep(i, 1, m) w[i] = 0;
		rep(i, 1, n) w[rk[x][rk[y][i]]]++;
		rep(i, 1, m) w[i] += w[i - 1];
		per(i, n, 1) sa[w[rk[x][rk[y][i]]]--] = rk[y][i];
		for (int i = m = 1; i <= n; i++)
		{
			int *a = rk[x] + sa[i], *b = rk[x] + sa[i - 1];
			rk[y][sa[i]] = *a == *b&&*(a + z) == *(b + z) ? m - 1 : m++;
		}
	}

	void getsa(int m)
	{
		//n = strlen(s + 1);
		rk[1][0] = now = sa[0] = s[0] = 0;
		rep(i, 1, m) w[i] = 0;
		rep(i, 1, n) w[s[i]]++;
		rep(i, 1, m) rk[1][i] = rk[1][i - 1] + (bool)w[i];
		rep(i, 1, m) w[i] += w[i - 1];
		rep(i, 1, n) rk[0][i] = rk[1][s[i]];
		rep(i, 1, n) sa[w[s[i]]--] = i;

		rk[1][n + 1] = rk[0][n + 1] = 0;	//多组的时候容易出bug
		for (int x = 1, y = rk[1][m]; x <= n && y <= n; x <<= 1) getsa(x, y);
		for (int i = 1, j = 0; i <= n; h[rk[now][i++]] = j ? j-- : j)
		{
			if (rk[now][i] == 1) continue;
			int k = n - max(sa[rk[now][i] - 1], i);
			while (j <= k && s[sa[rk[now][i] - 1] + j] == s[i + j]) ++j;
		}
	}

	void getrmq()
	{
		h[n + 1] = h[1] = lg[1] = 0;
		rep(i, 2, n) rmq[i][0] = h[i], lg[i] = lg[i >> 1] + 1;
		for (int i = 1; (1 << i) <= n; i++)
		{
			rep(j, 2, n)
			{
				if (j + (1 << i) > n + 1) break;
				rmq[j][i] = min(rmq[j][i - 1], rmq[j + (1 << i - 1)][i - 1]);
			}
		}
	}

	int lcp(int x, int y)
	{
		int l = min(rk[now][x], rk[now][y]) + 1, r = max(rk[now][x], rk[now][y]);
		return min(rmq[l][lg[r - l + 1]], rmq[r - (1 << lg[r - l + 1]) + 1][lg[r - l + 1]]);
	}

	void work()
	{
		GetS();	getsa(256); getrmq();
		int ans = 0, odd = 0, even = 0;
		rep(i, 1, n)
		{
		    odd = min(odd, h[i]), even = min(even, h[i]);
			if (sa[i] > n / 2) continue;
			int L = lcp(sa[i], n + 1 - sa[i]);
			ans += max(0, L - odd);  odd = max(L, odd);
			int R = sa[i] == 1 ? 0 : lcp(sa[i], n + 2 - sa[i]);
			ans += max(0, R - even); even = max(R, even);
		}
		printf("Case #%d: %d\n", ++cas, ans);
	}
}sa;

int main()
{
	T = read(); while (T--) sa.work();
	return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu 3948 The Number of Palindromes

后缀数组,求不同回文子串的数量 #include #include // hdu 3948 const int MAXN = 200010; int wa[MAXN], wb[MAXN], ...
  • solotzg
  • solotzg
  • 2013年07月28日 16:23
  • 661

HDU 3948 The Number of Palindromes(后缀数组)

题意:求一个串中不相同回文子串的个数。 做法:本来想用manacher。但是无法判重。只能利用后缀数组,按照求回文串常规做法,把原串翻转拼到原串后面,求出height,以及利用sparse tabl...
  • u012962816
  • u012962816
  • 2015年04月13日 16:01
  • 423

HDU 3948

UESTC的神题啊! 主要是去重比较难想 主要思想就是:按sa数组i从2开始枚举到n,pre1记录的是上一次计算过的回文串,所以先与height[i]取小值,代表这次计算重复的回文串,然后与实际的...
  • waitfor_
  • waitfor_
  • 2012年09月01日 17:48
  • 1501

HDOJ 3948 The Number of Palindromes 后缀数组

后缀数组求有多少个不同的回文串 The Number of Palindromes Time Limit: 6000/3000 MS (Java/Others)    Memory Lim...
  • u012797220
  • u012797220
  • 2015年04月05日 19:11
  • 562

【CF245H】【Queries for Number of Palindromes】

H. Queries for Number of Palindromes time limit per test 5 seconds memory limit per test ...
  • u013200703
  • u013200703
  • 2015年08月07日 19:25
  • 339

Hdu 3948 The Number of Palindromes 后缀数组+Manacher

The Number of Palindromes Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (J...
  • sinat_35406909
  • sinat_35406909
  • 2017年10月17日 19:56
  • 34

不同回文子串数目 hdu 3948

将原串反向后接在后面,中间用一个没出现过的字符隔开; 如"abab";k=strlen(str); 连接后变为"abab9baba0" 根据height【】排序后 i   height[i] ...
  • ddovetlose
  • ddovetlose
  • 2012年03月22日 13:14
  • 2097

HDU2029 Palindromes _easy version【入门】

Palindromes _easy version Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Ja...
  • tigerisland45
  • tigerisland45
  • 2016年07月05日 23:33
  • 1666

SPOJ Number of Palindromes(回文树)

SPOJ Number of Palindromes(回文树)
  • Dacc123
  • Dacc123
  • 2016年05月07日 19:39
  • 580

codeforces 245H Queries for Number of Palindromes 区间DP

题意:找特定范围内的回文数量 做法:基本的区间DP做法,可惜忘了... #include #include #include #define LMT 5002 using namespace s...
  • cqlf__
  • cqlf__
  • 2012年12月07日 22:20
  • 629
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDU 3948 The Number of Palindromes
举报原因:
原因补充:

(最多只允许输入30个字)