分析:实际上,我们用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;
}
}
//#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 中。。。 ) 刚学后缀数组 没能过