Tsinsen 题目A1393. Palisection(回文树)

来源:互联网 发布:ubuntu删除文件命令 编辑:程序博客网 时间:2024/06/06 00:47
A1393. Palisection
时间限制:2.0s   内存限制:256.0MB  
总提交次数:395   AC次数:144   平均分:59.15
将本题分享到:
      
   
查看未格式化的试题   提交   试题讨论
试题来源
  CODEFORCES 17E
问题描述
  给你一个长度 n (1 ≤ n ≤ 2·106) 的只由小写字母组成的字符串s。
  我们考虑s的所有连续且回文的子串集合P。位置不同但内容相同的两个串算作不同。
  问从P中选出两个串且他们在s中有公共位置的方法数有几个?
输入格式
  第一行一个整数n
  第二行字符串s
输出格式
  一行答案,输出结果对51123987取余。
样例输入
4
babb
样例输出
6
数据规模和约定
  10%的数据 n<=5
  15%的数据 n<=100
  25%的数据 n<=1000
  50%的数据 n<= 2·106
思路来自鸟神ORZ
有点坑的是相乘的时候会超int,所以要强制转换一下到long long 否则50分。。。
ac代码
提交序号提交时间语言结果得分风格分?时间使用空间使用
1202711
10-30 18:47
CPP
正确
100
56
187ms
249.0MB

#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>#define mod 51123987#define maxn 2000005#define N 26#define LL long longusing namespace std;struct P_tree{    int next[maxn][N];    int fail[maxn];    int cnt[maxn];    int len[maxn];    int s[maxn];    int n;    int last;    int p;    int num[maxn];    int newnode(int l)    {        for(int i=0;i<N;i++)            next[p][i]=0;        cnt[p]=0;        len[p]=l;        return p++;    }    void init()    {        p=0;        newnode(0);        newnode(-1);        last=0;        n=0;        s[n]=-1;        fail[0]=1;    }    int get_fail(int x)    {        while(s[n-len[x]-1]!=s[n])            x=fail[x];        return x;    }    int add(int c)    {        c-='a';        s[++n]=c;        int cur=get_fail(last);        if(!next[cur][c])        {            int now=newnode(len[cur]+2);            fail[now]=next[get_fail(fail[cur])][c];            next[cur][c]=now;            num[now]=num[fail[now]]+1;        }        last=next[cur][c];        cnt[last]++;        return num[last];    }    int count()    {        int i;        int ans=0;        for(i=p-1;i>=1;i--)/////////////        {            cnt[fail[i]]=(cnt[fail[i]]+cnt[i])%mod;            ans=(ans+cnt[i])%mod;        }        return ans;    }}T;char str[maxn];int n;int sf[maxn];void solve(){    int ans=0;    T.init();    sf[n]=0;    int i;    for(i=n-1;i>=0;i--)    {        sf[i]=(sf[i+1]+T.add(str[i]))%mod;    }    T.init();    for(i=0;i<n;i++)    {        ans=(ans+((LL)T.add(str[i])*sf[i+1])%mod)%mod;    }    int res=T.count();    res=(((LL)res*(res-1))/2)%mod;    printf("%d\n",((res-ans)+mod)%mod);}int main(){   // int n;    while(scanf("%d",&n)!=EOF)    {        scanf("%s",str);        solve();    }}


0 0
原创粉丝点击