A - Gao the string!
Time Limit:
2000/1000MS (Java/Others)
Memory Limit:
128000/64000KB (Java/Others)
Problem Description
give you a string, please output the result of the following function mod 1000000007
n is the length of the string
f() is the function of fibonacci, f(0) = 0, f(1) = 1...
a[i] is the total number of times any prefix appear in the suffix s[i....n-1].
(the prefix means s[0...i] )
Input
multiple test cases.
each test case will give you a string consists of lowercase letters, the length of which is no more than 100000.
Output
ouput a number.
Sample Input
aa
Sample Output
3
Hint
样例解释如下:
对于
aa这个后缀,前缀a出现了两次,前缀aa出现了一次,总共三次
对于a这个后缀,前缀a出现了一次
所以答案是f(3) + f(1)
先用EXKMP求出s串所有后缀和自身的所有最长公共前缀,即是nxt数组。然后用dp的思想不难求出,每一个位置所有后缀出现的次数和。再用矩阵快速幂求出答案即可,并不难。
AC代码:
//
// main.cpp
// Gao the string!
//
// Created by 蘇與軒 on 15/5/5.
// Copyright (c) 2015年 蘇與軒. All rights reserved.
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <set>
#include <algorithm>
#include <functional>
#define rep(i,a,b) for (int i=a;i<((b)+1);i++)
#define Rep(i,a,b) for (int i=a;i>=b;i--)
#define foreach(e,x) for (__typeof(x.begin()) e=x.begin();e!=x.end();e++)
#define mid ((l+r)>>1)
#define lson (k<<1)
#define rson (k<<1|1)
#define MEM(a,x) memset(a,x,sizeof a)
using namespace std;
const int N=100050;
const long long Mod=1000000007;
typedef pair<int, int> pii;
typedef long long ll;
char s[N];
ll ans;
int nxt[N];
struct Matrix {
ll num[2][2];
Matrix(){
MEM(num,0);
}
};
Matrix operator * (const Matrix &a,const Matrix &b) {
Matrix tmp;
rep(i,0,1) rep(j,0,1) rep(k,0,1) tmp.num[j][k]+=(a.num[j][i]*b.num[i][k])%Mod;
return tmp;
}
Matrix operator ^ (Matrix &a,ll x) {
Matrix tmp;
tmp.num[0][0]=1;tmp.num[1][1]=1;
while (x) {
if (x&1) tmp=tmp*a;
a=a*a;
x>>=1;
}
return tmp;
}
ll getans(ll x) {
if (x==0) return 0;
if (x<=2) return 1;
Matrix tmp;
tmp.num[0][0]=1;tmp.num[0][1]=1;
tmp.num[1][0]=1;
tmp=tmp^(x-1);
return tmp.num[0][0]%Mod;
}
int main(int argc, const char * argv[]) {
while (~scanf("%s",s)) {
int l=(int)strlen(s);
nxt[0]=l;
int p=0;
while (p+1<l&&s[p]==s[p+1]) p++;
nxt[1]=p;
int k=1,L;
rep(i,2,l-1) {
p=k+nxt[k]-1,L=nxt[i-k];
if (i+L<=p) nxt[i]=L;
else {
int j=p-i+1;
if (j<0) j=0;
while (i+j<l&&s[i+j]==s[j]) j++;
nxt[i]=j;k=i;
}
}
Rep(i,l-1,0) nxt[i]+=nxt[i+1];
ans=0;
rep(i,0,l-1) ans=(ans+getans(nxt[i]))%Mod;
printf("%lld\n",ans);
}
return 0;
}