问题套了一个斐波那契数,归根结底就是要求对于所有后缀s[i...n-1],所有前缀在其中出现的总次数。我一开始做的时候想了好久,后来看了别人的解法才恍然大悟。对于一个后缀来说 s[i...n-1]来说,所有与它匹配的前缀必然是和 s[i+1...n-1]  s[i+2...n-1] ....s[n-1..n-1]里的前缀匹配的,因而如果我们定义一个num[i]表示的是后缀s[i...n-1]与前缀的总长公共前缀,那么num[i]+num[i+1]+..num[n-1]就是前缀在后缀i里出现的次数总和,所以问题转化为求s[i...n-1]跟前缀的最长公共前缀,也可以理解成是  s[0...n-1]和s[i...n-1]求最长公共前缀。

求后缀的最长公共前缀,一个做法是后缀数组,然后建lcp,然后通过rmq询问,理论的复杂度nlogn,我自己套的模板用的是快排,所以后缀数组本身的复杂度就已经是nlog^2n,然后我就愉快的TLE了。

失败之后就只能转而用hash+二分,毕竟二分还是慢,所以我卡着时限过了这题,心有余悸。

#pragma warning(disable:4996)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <string>
#include <algorithm>
using namespace std; #define maxn 110000
#define ll long long
#define mod 1000000007
#define step 31 /*int rk[maxn], sa[maxn], lcp[maxn];
int tmp[maxn];
int d[maxn + 50][25];*/ int n; /*bool cmp_sa(int i, int j)
{
if (rk[i] != rk[j]) return rk[i] < rk[j];
else{
int ri = i + k <= n ? rk[i + k] : -1;
int rj = j + k <= n ? rk[j + k] : -1;
return ri < rj;
}
} void construct_sa(char *s, int *sa)
{
n = strlen(s);
for (int i = 0; i <= n; i++){
sa[i] = i;
rk[i] = i < n ? s[i] : -1;
}
for (k = 1; k <= n; k <<= 1){
sort(sa, sa + n + 1, cmp_sa);
tmp[sa[0]] = 0;
for (int i = 1; i <= n; i++){
tmp[sa[i]] = tmp[sa[i - 1]] + (cmp_sa(sa[i - 1], sa[i]) ? 1 : 0);
}
for (int i = 0; i <= n; i++){
rk[i] = tmp[i];
}
}
} void construct_lcp(char *s, int *sa, int *lcp)
{
n = strlen(s);
for (int i = 0; i <= n; i++) rk[sa[i]] = i;
int h = 0;
lcp[0] = 0;
for (int i = 0; i < n; i++){
int j = sa[rk[i] - 1];
for (h ? h-- : 0; i + h < n&&j + h < n&&s[i + h] == s[j + h]; h++);
lcp[rk[i] - 1] = h;
}
} void construct_rmq(int *lcp, int sizen)
{
for (int i = 0; i <= sizen; i++) d[i][0] = lcp[i];
for (int j = 1; (1 << j) <= sizen; j++){
for (int i = 0; (i + (1 << j) - 1) <= sizen; i++){
d[i][j] = min(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
}
}
} int rmq_query(int l, int r)
{
if (l > r) swap(l, r); r -= 1;
int k = 0; int len = r - l + 1;
while ((1 << (k + 1)) < len) k++;
return min(d[l][k], d[r - (1 << k) + 1][k]);
} */ char s[maxn];
ll num[maxn]; struct Matrix
{
ll a[2][2];
Matrix(){ memset(a, 0, sizeof(a)); }
}m; Matrix operator * (const Matrix &a,const Matrix &b){
Matrix ret;
for (int i = 0; i < 2; i++){
for (int j = 0; j < 2; j++){
for (int k = 0; k < 2; k++){
ret.a[i][j] += (a.a[i][k] * b.a[k][j]) % mod;
ret.a[i][j] %= mod;
}
}
}
return ret;
}
Matrix operator ^ (Matrix a,ll n){
Matrix ret;
for (int i = 0; i < 2; i++) ret.a[i][i] = 1;
while (n){
if (n & 1) ret = ret*a;
n >>= 1;
a = a*a;
}
return ret;
} ll cal(ll n)
{
m.a[0][0] = 0; m.a[0][1] = 1;
m.a[1][0] = 1; m.a[1][1] = 1;
m = m^n;
return m.a[0][1];
} ll seed[maxn];
ll h[maxn]; ll get(int l, int r){
return ((h[r] - h[l - 1] * seed[r - l + 1]%mod) + mod) % mod;
} int getlcp(int x)
{
if (get(1, 1) != get(x, x)) return 0;
int l = 1,r = n - x + 1;
while (l <= r){
int m = (l + r) >> 1;
if (get(1, 1 + m - 1) == get(x, x + m - 1)) l = m+1;
else r = m-1;
}
return r;
} int main()
{
seed[0] = 1;
for (int i = 1; i < maxn; i++){
seed[i] = seed[i - 1] * step%mod;
}
while (~scanf("%s", s + 1))
{
n = strlen(s + 1); h[0] = 0;
for (int i = 1; i <= n; i++){
h[i] = (h[i - 1] * step + s[i]) % mod;
}
num[1] = n;
for (int i = 2; i <= n; i++){
num[i] = getlcp(i);
}
ll ans = 0;
num[n + 1] = 0;
for (int i = n; i >= 1; i--){
num[i] += num[i + 1];
ans += cal(num[i]);
ans %= mod;
}
printf("%lld\n", ans);
}
return 0;
}

acdream1116 Gao the string!(hash二分 or 后缀数组)的更多相关文章

  1. acdream1116 Gao the string!(扩展KMP)

    今天是字符串填坑的一天,首先填的第一个坑是扩展KMP.总结一下KMP和扩展KMP的区别. 在这里s是主串,t是模式串. KMP可以求出的是以s[i]为结尾的串和 t前缀匹配的最长的长度.假如这个长度是 ...

  2. BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式( 二分答案 + 后缀数组 )

    二分答案m, 后缀数组求出height数组后分组来判断. ------------------------------------------------------------ #include&l ...

  3. bzoj 4310 跳蚤 二分答案+后缀数组/后缀树

    题目大意 给定\(k\)和长度\(\le10^5\)的串S 把串分成不超过\(k\)个子串,然后对于每个子串\(s\),他会从\(s\)的所有子串中选择字典序最大的那一个,并在选出来的\(k\)个子串 ...

  4. BZOJ3796 Mushroom追妹纸(二分答案+后缀数组+KMP)

    求出一个串使得这个串是\(s1,s2\)的子串.串中不包含\(s3\). 如果没有这个\(s3\)就可以二分答案,然后height小于二分值分一组.看看每组里是不是出现过\(s1,s2\)的后缀.判断 ...

  5. poj 1743 二分答案+后缀数组 求不重叠的最长重复子串

    题意:给出一串序列,求最长的theme长度 (theme:完全重叠的子序列,如1 2 3和1 2 3  or  子序列中每个元素对应的差相等,如1 2 3和7 8 9) 要是没有差相等这个条件那就好办 ...

  6. 2018.11.24 poj1743Musical Theme(二分答案+后缀数组)

    传送门 代码: 二分答案. 然后对于预处理的heightheightheight数组分成几段. 保证每一段中都是连续的几个heightheightheight并且这些heightheightheigh ...

  7. [BZOJ4556][TJOI2016&&HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1360  Solved: 545[S ...

  8. poj 3261 二分答案+后缀数组 求至少出现k次的最长重复子序列

    #include "stdio.h" #define maxn 20010 int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; int rank[ma ...

  9. 2018.11.24 poj3261Milk Patterns(后缀数组)

    传送门 后缀数组经典题. 貌似可以用二分答案+后缀数组? 我自己yyyyyy了一个好写一点的方法. 直接先预处理出heightheightheight数组. 然后对于所有连续的k−1k-1k−1个he ...

随机推荐

  1. Android--Fragment的懒加载

    我们都知道,fragment放在viewPager里面,viewpager会帮我们预先加载一个,但是当我们要看fragment里面的内容时,我们也许只会去看第一个,不会去看第二个,如果这时候不去实现f ...

  2. 转载:监控每个节点(Indices部分)

    集群的健康只是一个方面,它是对整个集群所有方面的一个很高的概括.节点状态的api是另外一个方面,它提供了关于你的集群中每个节点令你眼花缭乱的统计数据. 节点的状态提供了那么多的统计数据,在你很熟悉它们 ...

  3. [转]insmod

    [转]insmod http://www.cnblogs.com/amaoxiaozhu/archive/2013/03/08/2950002.html 在Linux下,驱动程序是内核的一部分,运行在 ...

  4. QT 按钮(4种样式)

    // 1.正常  btnNormal_ = new QPushButton("Normal Button", this);  // 2.可停驻  btnCheck_ = new Q ...

  5. Machine Learning 学习笔记 (1) —— 线性回归与逻辑回归

    本系列文章允许转载,转载请保留全文! [请先阅读][说明&总目录]http://www.cnblogs.com/tbcaaa8/p/4415055.html 1. 梯度下降法 (Gradien ...

  6. 通过find命令寻找文件并拷贝到一个指定目录方法详解

    有这样的一个需求,需要将一部分符合条件的文件从一个目录拷贝到另一个目录中,可以通过使用find命令从源目录查找到符合条件的文件然后使用cp命令拷贝到目标目录   将通过find命令找到的文件拷贝到一个 ...

  7. jira的插件

    jira的插件开发流程实践   怎么开头呢,由于自己比较懒,博客一直不怎么弄,以后克己一点,多传点自己遇到的问题和经历上来,供自己以后记忆,也供需要的小伙伴少走点弯路吧 最近公司项目需要竞标一个运维项 ...

  8. week 9 scenario testing

    1:How do you expect different personas to use your software?  What’s their need and their goals,  ho ...

  9. 11.2Daily Scrum

    人员 任务分配完成情况 明天任务分配 王皓南 做文件的网页和数据库连接,任务编号771 实现视频上传的功能 申开亮 实现视频浏览的功能,任务编号772 实现视频浏览的功能 王宇杰 后台测试,任务编号7 ...

  10. java设计模式类图大全

    近来在看书实现GoF的23个设计模式,自己一点点地用建模工具按照自己的理解画出类图(是比较符合我个人思考理解的,个人觉得比通用类图更详细些),碰巧找到了一个挺好用的UML建模工具StarUML,也刚好 ...