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

acdream 1116 Gao the string!

时间:2015-01-30 22:45:56      阅读:318      评论:0      收藏:0      [点我收藏+]

标签:图论   扩展kmp   

        分析:实际上,我们用next[i]表示 T[i-n] 和T[1-n]的最长公共前缀,那么a[i]=next[i] +next[i+1]...... +next[n];  最长公共前缀(lcp)有3种方法 : 扩展kmp  ,hash 和后缀数组 。


方法一  :扩展kmp 

//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstring>
#include<map>
#include<vector>
#include<set>
#include<ctime>
#include<stdlib.h>
using namespace std;
const int mmax= 100010;
const int mod=1000000007;
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
typedef long long LL;
//typedef unsigned long long ULL;
struct mar
{
    LL a[2][2];
    mar()
    {
        a[0][0]=a[0][1]=a[1][0]=1;
        a[1][1]=0;
    }
    mar operator * (const mar &A)
    {
        mar B;
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<2;j++)
            {
                B.a[i][j]=0;
                for(int k=0;k<2;k++)
                    B.a[i][j]+=a[i][k]*A.a[k][j];
                 B.a[i][j]%=mod;
            }
        }
        return B;
    }
    void pri()
    {
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                printf("%lld%c",a[i][j],j==1?'\n':' ');
    }
};

mar unit()
{
    mar aa;
    aa.a[0][0]=aa.a[1][1]=1;
    aa.a[0][1]=aa.a[1][0]=0;
    return aa;
}
mar powmod(mar A,LL n)
{
    mar res=unit();
    mar tmp=A;
    for(;n;n/=2)
    {
        if(n&1)
            res=res*tmp;
        tmp=tmp*tmp;
    }
    return res;
}
LL getFib(LL n)
{
    if(n==0)
        return 0;
    if(n==1)
        return 1;
    mar B;
    mar AA=powmod(B,n-1);
    return AA.a[0][0];
}




int next[mmax];

void get_next(char *s)
{
    int n=strlen(s);
    int i,j,k;
    for(j=0;1+j<n && s[j]==s[1+j];j++);
    next[1]=j;
    k=1;
    for(i=2;i<n;i++)
    {
        int len=k+next[k],L=next[i-k];
        if(L<len-i)
            next[i]=L;
        else
        {
            for(j=max(0,len-i);i+j<n && s[j]==s[i+j];j++);
            next[i]=j;
            k=i;
        }
    }
    next[0]=n;
}

char str[mmax];
int main()
{
    while(scanf("%s",str)!=EOF)
    {
        int n=strlen(str);
        memset(next,0,sizeof next);
        get_next(str);
        LL sum=0;
        for(int i=n-1;i>=0;i--)
        {
            next[i]+=next[i+1];
            sum+=getFib(next[i]);
            sum%=mod;
        }
        cout<<sum<<endl;
    }
}


方法2: hash

//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstring>
#include<map>
#include<vector>
#include<set>
#include<ctime>
#include<stdlib.h>
using namespace std;
const int mmax= 100010;
const int mod=1000000007;
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
typedef long long LL;
typedef unsigned long long ULL;
struct mar
{
    LL a[2][2];
    mar()
    {
        a[0][0]=a[0][1]=a[1][0]=1;
        a[1][1]=0;
    }
    mar operator + (const mar &A)
    {
        mar B;
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
            {
                B.a[i][j]=a[i][j]+A.a[i][j];
                B.a[i][j]%=mod;
            }
        return B;
    }
    mar operator * (const mar &A)
    {
        mar B;
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<2;j++)
            {
                B.a[i][j]=0;
                for(int k=0;k<2;k++)
                {
                    B.a[i][j]+=a[i][k]*A.a[k][j];
                    B.a[i][j]%=mod;
                }
            }
        }
        return B;
    }
    void pri()
    {
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                printf("%lld%c",a[i][j],j==1?'\n':' ');
    }
};

mar unit()
{
    mar aa;
    aa.a[0][0]=aa.a[1][1]=1;
    aa.a[0][1]=aa.a[1][0]=0;
    return aa;
}
mar powmod(mar A,LL n)
{
    mar res=unit();
    mar tmp=A;
    for(;n;n/=2)
    {
        if(n&1)
            res=res*tmp;
        tmp=tmp*tmp;
    }
    return res;
}
LL getFib(LL n)
{
    if(n==0)
        return 0;
    if(n==1)
        return 1;
    mar B;
    mar AA=powmod(B,n-1);
    return AA.a[0][0]%mod;
}





char str[mmax];
ULL  Ha[mmax];
ULL  Pow[mmax];
void get_hash(char *s)
{
    Ha[0]=0;
    Pow[0]=1;
    for(int i=0;s[i];i++)
    {
        Pow[i+1]=Pow[i]*131;
        Ha[i+1]=Ha[i]+Pow[i]*s[i];
    }
}
LL cnt[mmax];
int main()
{
    while(scanf("%s",str)!=EOF)
    {
        int n=strlen(str);
        get_hash(str);
        for(int i=1;i<=n;i++)
        {
            int l=i,r=n+1;
            while(l<r)
            {
                int mid=(l+l)>>1;
                if(Ha[mid]-Ha[i-1]==Ha[mid-i+1]*Pow[i-1])
                    l=mid+1;
                else
                    r=mid;
            }
            cnt[i]=r-i;
        }
        for(int i=n-1;i>=1;i--)
            cnt[i]+=cnt[i+1];
        LL sum=0;
        for(int i=1;i<=n;i++)
        {
            sum+=getFib(cnt[i]);
            sum%=mod;
        }
        cout<<sum<<endl;
    }
    return 0;
}


方法3:后缀数组 (TLE 中。。。 )   刚学后缀数组  没能过


acdream 1116 Gao the string!

标签:图论   扩展kmp   

原文地址:http://blog.csdn.net/u012127882/article/details/43311611

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