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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章