Acdreamoj1116(Gao the string!)字符串hash+二分+矩阵快速幂

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] )

解法:如果知道了num[i]表示i开始的后缀s[i....n]跟前缀s[1...]之间的公共的前缀,那么以i开头的后缀中就匹配了num[i]个前缀了

所以i这个后缀出现的前缀的数量实际上就是num[i] + num[i+1] + .. num[n]. 求出来之后快速幂求斐波那契数列相应项大小即可。求lcp的时候是二分+hash;字符串hash中,seed为31(java库源码中是这个数,应该是效果比较好的)

代码:

/******************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;

#define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef long long LL;
const int Max=100010;
const int INF=1000000007;
const int hashseed=31;

LL seed[Max];
LL has[Max];
char s[Max];
LL num[Max];
int len=0;
struct matrix
{
    LL num[2][2];
    matrix()
    {
        memset(num,0,sizeof num);
    }
};
matrix operator*(const matrix& a,const matrix& b)
{
    matrix ans;
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
        for(int k=0;k<2;k++)
        ans.num[j][k]+=(a.num[j][i]*b.num[i][k])%INF;
    return ans;
}
matrix operator^(matrix a,LL n)
{
    matrix ans;
    ans.num[0][0]=1;
    ans.num[1][1]=1;
    while(n)
    {
        if(n&1)
        {
            ans=ans*a;
        }
        a=a*a;
        n>>=1;
    }
    return ans;
}
LL getans(LL t)
{
    if(t==0)
        return 0;
    if(t<=2)
        return 1;
    matrix tool;
    tool.num[0][0]=1;
    tool.num[0][1]=1;
    tool.num[1][0]=1;
    tool=tool^(t-1);
    return tool.num[0][0]%INF;
}
void init()
{
    seed[0]=1;
    for(int i=1; i<Max; i++)
        seed[i]=(seed[i-1]*hashseed)%INF;
}
LL Hash(int i,int L)
{
    return ((has[i]-has[i+L]*seed[L])%INF+INF)%INF;
}
bool OK(int i,int l)
{
    return Hash(0,l)==Hash(i,l);
}
void getnum(int i)
{
    int left=i,right=len-1;
    while(left<=right)
    {
        int middle=(left+right)/2;
        if(OK(i,middle-i+1))
            left=middle+1;
        else
            right=middle-1;
    }
    num[i]=right-i+1;
}
void makehash()
{
    for(int i=len-1;i>=0;i--)
    {
        has[i]=(has[i+1]*hashseed+s[i])%INF;
    }
    num[0]=len;
    for(int i=1;i<len;i++)
    {
        getnum(i);
    }
}
int main()
{
    init();
   while(scanf("%s",s)==1)
   {
       memset(has,0,sizeof has);
       len=strlen(s);
       makehash();
       for(int i=len-1;i>=0;i--)
        num[i]+=num[i+1];
       LL ans=0;
       for(int i=0;i<len;i++)
        ans=(ans+getans(num[i]))%INF;
       cout<<ans<<'\n';
   }
    return 0;
}

Acdreamoj1116(Gao the string!)字符串hash+二分+矩阵快速幂

时间: 2024-11-09 05:22:52

Acdreamoj1116(Gao the string!)字符串hash+二分+矩阵快速幂的相关文章

HDU5863 cjj&#39;s string game(DP + 矩阵快速幂)

题目 Source http://acm.split.hdu.edu.cn/showproblem.php?pid=5863 Description cjj has k kinds of characters the number of which are infinite. He wants to build two strings with the characters. The lengths of the strings are both equal to n. cjj also def

Matrix Power Series(矩阵快速幂)

矩阵快速幂:http://www.cnblogs.com/kuangbin/archive/2012/08/17/2643347.html Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 16341   Accepted: 6966 Description Given a n × n matrix A and a positive integer k, find the sum S

bnu 34985 Elegant String(矩阵快速幂+dp推导公式)

Elegant String Time Limit: 1000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main Prev Submit Status Statistics Discuss Next Type: None None Graph Theory      2-SAT     Articulation/Bridge/Biconnected Component      Cy

BNUOJ 34985 Elegant String 2014北京邀请赛E题 动态规划 矩阵快速幂

Elegant String Time Limit: 1000msMemory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main We define a kind of strings as elegant string: among all the substrings of an elegant string, none of them is a permutation of "0, 1,-, k

hdu1588 Gauss Fibonacci(矩阵快速幂+二分求矩阵等比和)

题目: Gauss Fibonacci Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2858    Accepted Submission(s): 1186 Problem Description Without expecting, Angel replied quickly.She says: "I'v heard that y

POJ 3233-Matrix Power Series(矩阵快速幂+二分求矩阵和)

Matrix Power Series Time Limit:3000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3233 Appoint description:  System Crawler  (2015-02-28) Description Given a n × n matrix A and a positive integer k, find the

2017 ECJTU ACM程序设计竞赛 矩阵快速幂+二分

矩阵 Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other) Total Submission(s) : 7   Accepted Submission(s) : 4 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description 假设你有一个矩阵,有这样的运算A^(n+1) = A^(n)*A (*代

HDU 5863 cjj&#39;s string game ( 16年多校10 G 题、矩阵快速幂优化线性递推DP )

题目链接 题意 : 有种不同的字符,每种字符有无限个,要求用这k种字符构造两个长度为n的字符串a和b,使得a串和b串的最长公共部分长度恰为m,问方案数 分析 : 直觉是DP 不过当时看到 n 很大.但是 m 很小的时候 发现此题DP并不合适.于是想可能是某种组合数学的问题可以直接公式算 看到题解的我.恍然大悟.对于这种数据.可以考虑一下矩阵快速幂优化的DP 首先要想到线性递推的 DP 式子 最直观的想法就是 dp[i][j] = 到第 i 个位置为止.前面最长匹配长度为 j 的方案数 但是如果仔

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分)

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define MAX_SIZE 30 #define CLR( a, b ) memset( a, b, sizeof(a) ) int MOD = 0; int n, k; st