分析:实际上,我们用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 中。。。 ) 刚学后缀数组 没能过
时间: 2024-10-26 10:46:40