51nod 1464 半回文(dp,Trie)

来源:互联网 发布:博达软件 编辑:程序博客网 时间:2024/06/11 23:58

参考题解:http://blog.csdn.net/haut_ykc/article/details/77933792
第一发是把所有半回文串放进了字典树,搜一发,半回文串是暴力找的,有两组数据超时。
看这个题解讲的挺好,用dp对半回文串预处理,dp[i][j]==true表示i开头的子串,以j结尾的子串是个半回文串,vis[i]表示以i开头的半回文串最远能够延伸到哪个位置。

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int MAXN = 6005;char s[MAXN];string ans;bool dp[MAXN][MAXN];int k,vis[MAXN];int siz,Trie[MAXN*1000][2];int num[MAXN*1000];void insert(int st){    int i, now = 0;    for (i = st; i <= vis[st]; i++)    {        int v = s[i] - 'a';        if (Trie[now][v] == 0)            Trie[now][v] = ++siz;        if (dp[st][i])            num[Trie[now][v]]++;        now = Trie[now][v];    }}void dfs(int x){    string tmp = ans;    if (k > 0 && Trie[x][0])    {        k -= num[Trie[x][0]];        ans = ans + 'a';        dfs(Trie[x][0]);    }    if (k > 0 && Trie[x][1])    {        ans = tmp;        k -= num[Trie[x][1]];        ans = ans + 'b';        dfs(Trie[x][1]);    }}void init(int len){    for (int i = len-1; i >= 0; i--)    {        dp[i][i] = true;        vis[i] = i;        for (int j = i + 1; j < len; j++)        {            if (s[i] == s[j])            {                if (i + 2 >= j - 2)                    dp[i][j] = 1;                else                    dp[i][j] = dp[i + 2][j - 2];            }            if (dp[i][j])                vis[i] = j;        }    }}int main(void){    scanf("%s", s);    scanf("%d", &k);    int len = strlen(s);    init(len);    for (int i = 0; i < len; i++)        insert(i);    dfs(0);    cout << ans << endl;    return 0;}
原创粉丝点击