码迷,mamicode.com
首页 > 其他好文 > 详细

Finding Palindromes - 猥琐的字符串(Manacher+trie)

时间:2015-08-21 20:58:12      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:有 N 个字符串,所有的字符串长度不超过 200W 任意俩俩字符串可以自由组合,问组合的字符串是回文串的个数有多少个?
 
分析:这是一个相当猥琐的字符串处理,因为没有说单个的字符串最少多长,所以很可能会有这样的情况,200w个字符串,每个字符串长度1,或者1个串,这个串的长度是100w, 为了对付这种猥琐的方式可以用一个长为100w的字符串保存所有的串,然后用另一个数组记录每个字符串所在的区间。匹配的时候可以使用trie因为回文串是两端匹配,所以插入trie的时候可以倒着插入,不过查询的时候会出现两种情况,一种是这个字符串已经匹配完,不过他后面匹配的字符串没有完,另一种是这个字符串匹配完还有剩余长度,不管哪种情况都需要判断一下剩余的串是否是回文串,tire里面的保存后缀,匹配串保存的是前缀。
 
代码如下:
================================================================================================================
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = 2e6+7;
const int oo = 1e9+7;

struct Trie
{///字典树的节点
    int next[26];
    int leaf;///以这个节点为终点的叶子节点个数
    int count;///后面回文串的数量

    void Free()
    {
        leaf = count = 0;
        memset(next, false, sizeof(next));
    }

}trie[MAXN];

int top;///配合字典树使用,top表示没有使用的内存
int start[MAXN], p[MAXN<<1];
char MumStr[MAXN], Estr[MAXN<<1];
bool suffix[MAXN];///后缀是否是回文串
bool prefix[MAXN];///前缀是否是回文串

void BuildTrie(int n)
{
    int p = 0;

    for(int i=start[n+1]-1; i>=start[n]; i--)
    {///把字符串倒插进去
        int k = MumStr[i] - a;

        trie[p].count += prefix[i];

        if(trie[p].next[k] == 0)
        {
            trie[p].next[k] = ++top;
            trie[top].Free();
        }
        p = trie[p].next[k];
    }

    trie[p].leaf += 1;
}
void Manacher(int n)
{
    int i, id=0, len=1;

    Estr[0] = $;

    for(i=start[n]; i<start[n+1]; i++)
    {
        Estr[len++] = #;
        Estr[len++] = MumStr[i];

        suffix[i] = false;
        prefix[i] = false;
    }
    Estr[len] = #;
    Estr[len+1] = 0;

    for(i=2; i<len; i++)
    {
        p[i] = 1;

        if(p[id]+id > i)
            p[i] = min(p[id*2-i], p[id]+id-i);

        while(Estr[ i+p[i] ] == Estr[ i-p[i] ])
            p[i]++;

        if(p[id]+id < p[i]+i)
            id = i;

        if(p[i] == i)
            prefix[ start[n]+p[i]-2 ] = true;
        if(p[i]+i-1 == len)
            suffix[ start[n+1]-p[i]+1 ] = true;
    }
}
int Query(int n)
{
    int i, p=0, sum = 0;

    for(i=start[n]; i<start[n+1]; i++)
    {
        int k = MumStr[i] - a;

        if(trie[p].next[k] == 0)
            break;

        p = trie[p].next[k];

        if(suffix[i+1] || i==start[n+1]-1)
            sum += trie[p].leaf;
    }

    if(i == start[n+1])
        sum += trie[p].count;

    return sum;
}

int main()
{
    int N;

    while(scanf("%d", &N) != EOF)
    {
        int i, len;

        top = 0;
        trie[0].Free();

        for(i=1; i<=N; i++)
        {
            scanf("%d%s", &len, MumStr+start[i]);
            start[i+1] = start[i] + len;

            Manacher(i);
            BuildTrie(i);
        }

        long long ans = 0;

        for(i=1; i<=N; i++)
            ans += Query(i);

        printf("%lld\n", ans);
    }

    return 0;
}
/**
2
3 abc
4 acba

*/

 

Finding Palindromes - 猥琐的字符串(Manacher+trie)

标签:

原文地址:http://www.cnblogs.com/liuxin13/p/4748749.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!