ACdream 字符串专题A Gao the string! EXKMP+矩阵快速幂

来源:互联网 发布:simon d 知乎 编辑:程序博客网 时间:2024/06/04 05:25

A - Gao the string!

Time Limit: 2000/1000MS (Java/Others)    Memory Limit: 128000/64000KB (Java/Others)
Submit Status

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;}



0 0
原创粉丝点击