Codeforces 577E Ann and Half-Palindrome 字典树

题目链接

题意:

若一个字符串是半回文串,则满足第一位和最后一位相等, 第三位和倒数第三位相等,如此类推。

给定一个字符串s,输出s的所有子串中的半回文串字典序第k大的 字符串。


good[i][j] 表示 s(i,j) 是半回文串。

把这些回文串插到字典树里 在字典树上找第k个叶子节点。

插入时:插入以i点开头的所有半回文串。


#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cstdio>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
using namespace std;
template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
	if (x < 0) {
		putchar('-');
		x = -x;
	}
	if (x > 9) pt(x / 10);
	putchar(x % 10 + '0');
}
typedef int ll;
typedef pair<int, int> pii;
const int inf = 1e9;
const int N = 5005;
bool good[N][N];
#define Word_Len 5050000  
#define Sigma_size 2  

struct <span class="KSFIND_CLASS_SELECT" id="0KSFindDIV">Trie</span> {
	ll ch[Word_Len][Sigma_size], sz;     //Word_Len是字典树的节点数 若都是小写字母Sigma_size=26 sz为当前节点数  
	ll Have_word[Word_Len];      //这个节点下有几个单词  
	ll val[Word_Len];                // 这个节点附带的信息,初始化为0表示这个节点不存在单词,所以节点带的信息必须!=0  
	ll pre[Word_Len];
	char he[Word_Len];
	ll Newnode() { memset(ch[sz], 0, sizeof(ch[sz])); val[sz] = Have_word[sz] = 0; return sz++; }
	void init()                          //初始化字典树  
	{
		sz = 0; Newnode();
	}//初始化  
	ll idx(char c) { return c - 'a'; }     //字符串编号  

	int insert(char *s, int start) {     //把v数字加给 s单词最后一个字母  
		ll u = 0;
		for (ll i = 0; s[i]; i++) {
			ll c = idx(s[i]);
			if (!ch[u][c])            //节点不存在就新建后附加  
			{
				ch[u][c] = Newnode();
				he[sz - 1] = s[i];
				pre[sz - 1] = u;
			}
			u = ch[u][c];
			if (good[start][start + i]) Have_word[u]++;
		}
		return u;
	}
	void dfs(int u) {
		val[u] += Have_word[u];
		for (int i = 0; i < Sigma_size; i++)
		{
			int v = ch[u][i];	if (!v)continue;
			dfs(v);
			val[u] += val[v];
		}
	}
	int find_kth(int u, int k) {
		if (u)putchar(he[u]);
		if (k <= Have_word[u])return u;
		k -= Have_word[u];
		for (int i = 0; i < Sigma_size; i++)
		{
			int v = ch[u][i];	if (!v)continue;
			if (k <= val[v])
			{
				return find_kth(v, k);
			}
			else k -= val[v];
		}
	}
} ac;
int n, k;
char s[N];
int main() {
	scanf("%s", s);
	rd(k);
	n = strlen(s);
	for (int i = 0; i < n; i++)
	{
		for (int l = i, r = i; l >= 0 && r < n; l --, r ++) 
		{
			if (s[l] == s[r])
				if (l + 2 >= r - 2 || r - 2 < 0 || l + 2 >= n || good[l + 2][r - 2])
					good[l][r] = true;			
		}
		for (int l = i, r = i + 1; l >= 0 && r < n; l --, r ++)
		{
			if (s[l] == s[r])
				if (l + 2 >= r - 2 || r - 2 < 0 || l + 2 >= n || good[l + 2][r - 2])
				good[l][r] = true;
		}
	}

	ac.init();
	for (int i = 0; i < n; i++)
	{
		int j = n - 1;
		while (good[i][j] == false)j--;
		char c = s[j + 1]; s[j + 1] = 0;
		ac.insert(s + i, i);
		s[j + 1] = c;
	}

	ac.dfs(0);
	ac.val[0] = 0;
	ac.find_kth(0, k);
	return 0;
}


ti
tri
Trie

你可能感兴趣的:(Codeforces 577E Ann and Half-Palindrome 字典树)