找出s的子串中字典序第k小的“半回文串” Trie Codeforce Div. 2 Ann and Half-Palindrome

http://codeforces.com/problemset/problem/557/E

题意

找出s的子串中字典序第k小的“半回文串”,给出半回文串定义是:对于任意i<=|s|/2 有s[i] = s[len-i+1]

思路

这用dp推下就可以了,dp[i][j]表从i到j是否是回文串 
则dp[i][j] = dp[i+2][j-2](j-i>=4),其他的都是奇回文串; 
要输出第k个字典序的子串,首先肯定想到要用字典树输出来就是了,很简单的dfs就可以了。插入串的时候,就不要一个一个插了,而直接插一个后缀就可以了这样总的复杂度也就是O(n * n),n是串的长度。

http://codeforces.com/blog/entry/18943

This problem can be solved with help of dynamic programming.

At first we calculate matrix good[][]. In good[i][j] we put true, if substring from position i to position j half-palindrome. Else we put ingood[i][j]false. We can do it with iterating on "middle" of half-palindrome and expanding it to the left and to the right. There are 4 cases of "middle" but we omit it because they are simple enough.

Now we need to use Trie and we will put in it suffixes of given string. Also we will store array cnt[]. In cnt[v] we will store number of half-palindromes which ends in vertex v of our Trie. Let now we put in tree suffix which starts in position i, current symbol of string which we put is in position j and we go in vertex v of out Trie. Then if good[i][j] = true we add one to cnt[v].

Now with help of dfs let calculate for every vertex sum[v] — sum of numbers which stored in array cnt[] for vertex v and for vertices in all subtrees of vertex v.

It is left only to restore answer. Start from root of our Trie. We will store answer in variable ans. In variable k store number of required substring. Let now we in vertex v, by letter 'a' we can go in vertex toa and by letter 'b' — in vertex tob.

Then if sum[toa] ≤ k we make ans +  = 'a' and go in vertex toa of our Trie. Else we need to make as follows: k —  = sum[toa],ans +  = 'b' and go in vertex tob of our Trie.

When k will be  ≤ 0 print resulting string ans and finish algorithm.

Asymptotic behavior of this solution — O(szalph * n2) where szalph — size of input alphabet (in this problem it equals to two) and n — length of given string.

http://codeforces.com/contest/557/submission/13470601

#include
#include
#include
#include

#define For(i,x,y) for (int i=x;i=R?1:(s[L]==s[R]&&DP(L+2,R-2));
}

//Trie
int son[Top][2],cnt[Top],Sum[Top],tot,x,t,y;

void DFS(int x)
{
	Sum[x]=cnt[x];
	For(i,0,2) if (int y=son[x][i]) DFS(y),Sum[x]+=Sum[y];
}
void DFS_2(int x)
{
	if (k<=cnt[x]) return;k-=cnt[x];
	For(i,0,2)
		if (int y=son[x][i])
			if (k>Sum[y]) k-=Sum[y];else {Ans.Pb(i+'a'),DFS_2(y);break;}
}

int main()
{
	memset(f,-1,sizeof(f));
	scanf("%s%d",s,&k);n=strlen(s);
	For(i,0,n) For(j,i,n) f[i][j]=DP(i,j);
	For(i,0,n)
	{
		x=0;
		For(j,i,n)
		{
			int &u=son[x][s[j]-'a'];
			if (!u) u=++tot;x=u;
			if (f[i][j]) cnt[x]++;
		}
	}
	DFS(0);
	DFS_2(0);
	puts(Ans.c_str());
}


你可能感兴趣的:(Trie)