Description

SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999。
他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C', 'D'。现在他要求蒟蒻yts1999构造一个新的字符串S,构造的方法是:进行多次操作,每一次操作选择T的一个子串,将其加入S的末尾。
对于一个可构造出的字符串S,可能有多种构造方案,Oxer定义构造字符串S所需的操作次数为所有构造方案中操作次数的最小值。
Oxer想知道对于给定的正整数N和字符串T,他所能构造出的所有长度为N的字符串S中,构造所需的操作次数最大的字符串的操作次数。
蒟蒻yts1999当然不会做了,于是向你求助。

Input

第一行包含一个整数N,表示要构造的字符串长度。
第二行包含一个字符串T,T的意义如题所述。

Output

输出文件包含一行,一个整数,为你所求出的最大的操作次数。

Sample Input

5
ABCCAD

Sample Output

5

HINT

【样例说明】
例如字符串"AAAAA",该字符串所需操作次数为5,不存在能用T的子串构造出的,且所需操作次数比5大的字符串。
【数据规模和约定】
对于100%的数据,1 ≤ N ≤ 10^18,1 ≤ |T| ≤ 10^5。

Solution

一篇写的很好的博客

Code

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<queue>
  5. #define N (200009)
  6. #define LL long long
  7. using namespace std;
  8.  
  9. LL n,id;
  10. char s[N];
  11. queue<int>Q;
  12. int dis[N],vis[N];
  13.  
  14. struct Matrix
  15. {
  16. LL m[][];
  17. Matrix(){memset(m,,sizeof(m));}
  18.  
  19. Matrix operator * (const Matrix &b) const
  20. {
  21. Matrix c;
  22. for (int i=; i<; ++i)
  23. for (int j=; j<; ++j)
  24. c.m[i][j]=1e18;
  25. for (int k=; k<; ++k)
  26. for (int i=; i<; ++i)
  27. for (int j=; j<; ++j)
  28. c.m[i][j]=min(c.m[i][j],m[i][k]+b.m[k][j]);
  29. return c;
  30. }
  31. }A,G;
  32.  
  33. Matrix Qpow(Matrix a,LL b)
  34. {
  35. Matrix ans;
  36. for (int i=; i<; ++i) ans.m[i][i]=;
  37. while (b)
  38. {
  39. if (b&) ans=ans*a;
  40. a=a*a; b>>=;
  41. }
  42. return ans;
  43. }
  44.  
  45. struct SAM
  46. {
  47. int son[N][],fa[N],step[N];
  48. int p,q,np,nq,last,cnt;
  49. SAM(){last=cnt=;}
  50.  
  51. void Insert(int x)
  52. {
  53. p=last; np=last=++cnt; step[np]=step[p]+;
  54. while (p && !son[p][x]) son[p][x]=np, p=fa[p];
  55. if (!p) fa[np]=;
  56. else
  57. {
  58. q=son[p][x];
  59. if (step[q]==step[p]+) fa[np]=q;
  60. else
  61. {
  62. nq=++cnt; step[nq]=step[p]+;
  63. memcpy(son[nq],son[q],sizeof(son[q]));
  64. fa[nq]=fa[q]; fa[q]=fa[np]=nq;
  65. while (son[p][x]==q) son[p][x]=nq, p=fa[p];
  66. }
  67. }
  68. }
  69. void Build_Matrix()
  70. {
  71. for (int i=; i<; ++i)
  72. for (int j=; j<; ++j)
  73. A.m[i][j]=1e18;
  74. for (int s=; s<; ++s)
  75. {
  76. while (!Q.empty()) Q.pop();
  77. memset(vis,false,sizeof(vis));
  78. vis[son[][s]]=true;
  79. Q.push(son[][s]); dis[son[][s]]=;
  80. while (!Q.empty())
  81. {
  82. int x=Q.front(); Q.pop();
  83. for (int i=; i<; ++i)
  84. if (son[x][i] && !vis[son[x][i]])
  85. vis[son[x][i]]=true,Q.push(son[x][i]),dis[son[x][i]]=dis[x]+;
  86. else A.m[s][i]=min(A.m[s][i],(LL)dis[x]);
  87. }
  88. }
  89. }
  90. }SAM;
  91.  
  92. LL check(LL x)
  93. {
  94. LL Min=1e18;
  95. G=Qpow(A,x);
  96. for (int i=; i<; ++i)
  97. for (int j=; j<; ++j)
  98. Min=min(Min,G.m[i][j]);
  99. return Min>=n;
  100. }
  101.  
  102. int main()
  103. {
  104. scanf("%lld%s",&n,s);
  105. for (int i=,l=strlen(s); i<l; ++i)
  106. SAM.Insert(s[i]-'A');
  107. SAM.Build_Matrix();
  108. LL l=,r=1e18,ans;
  109. while (l<=r)
  110. {
  111. LL mid=(l+r)>>;
  112. if (check(mid)) ans=mid,r=mid-;
  113. else l=mid+;
  114. }
  115. printf("%lld\n",ans);
  116. }

BZOJ4180:字符串计数(SAM,二分,矩阵乘法)的更多相关文章

  1. 【BZOJ 4180】 4180: 字符串计数 (SAM+二分+矩阵乘法)

    4180: 字符串计数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 164  Solved: 75 Description SD有一名神犇叫做Oxe ...

  2. BZOJ 4180: 字符串计数 后缀自动机 + 矩阵乘法 + 二分(神题)

    Description SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999.   他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C ...

  3. 【BZOJ-4180】字符串计数 后缀自动机 + 矩阵乘法

    4180: 字符串计数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 146  Solved: 66[Submit][Status][Discuss] ...

  4. POJ 3233 Matrix Power Series 二分+矩阵乘法

    链接:http://poj.org/problem?id=3233 题意:给一个N*N的矩阵(N<=30),求S = A + A^2 + A^3 + - + A^k(k<=10^9). 思 ...

  5. [BZOJ4180] 字符串计数

    膜一发KsCla巨佬 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5 ...

  6. 【清澄A1333】【整体二分+二维树状数组】矩阵乘法(梁盾)

    试题来源 2012中国国家集训队命题答辩 问题描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入格式 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共 ...

  7. BZOJ 2738: 矩阵乘法 [整体二分]

    给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 愚蠢的名字...... 整体二分,影响因子就是矩阵里的数 把$\le mid$的矩阵元素加到二维树状数组里然后询问分成两组就行 ...

  8. BZOJ_2738_矩阵乘法_整体二分

    BZOJ_2738_矩阵乘法_整体二分 Description 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. Input 第一行两个数N,Q,表示矩阵大小和询问组数: 接下 ...

  9. BZOJ_4002_[JLOI2015]有意义的字符串_矩阵乘法

    BZOJ_4002_[JLOI2015]有意义的字符串_矩阵乘法 Description B 君有两个好朋友,他们叫宁宁和冉冉.有一天,冉冉遇到了一个有趣的题目:输入 b;d;n,求 Input 一行 ...

随机推荐

  1. Java多态-如何理解父类引用指向子类对象

    java多态,如何理解父类引用指向子类对象 要理解多态性,首先要知道什么是“向上转型”. 我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类.我可以通过   Cat c = new ...

  2. SpringMVC的controller层接收来自jsp页面通过<a href="/user/userUpdateInfo/>的中文乱码问题

    这种情况是,jsp页面的中文正常显示,数据的中文也是正常显示,但是在Controller层接收到的中文是乱码,如下图所示: 解决方法:在Controller层对前台传递的中文乱码进行处理,将它转换成u ...

  3. java自学-基本数据类型

     java中也有对数据的运算处理,java中数据分为常量和变量,常量就是直接固定不变的数据,变量是数据可能发生改变的数据,如下: int a=0; a=1+1; 上边代码,a就是变量,初始为0,接下来 ...

  4. JAVA非静态成员变量之死循环

    1.非静态成员变量 当成员变量为非静态成员变量且对当前类进行实例化时,将会产生死循环 例子: public class ConstructorCls { private ConstructorCls ...

  5. 为什么要用 C# 来作为您的首选编程语言

    因为您可以用,并且也是您的最佳选择!之所以可用,是因为 C# 能够很好地在 Mac.Linux.Android 和 iOS 上运行(对了,还有 Windows):它可以在您最喜爱的编辑器上运行:它在一 ...

  6. Linux学习7-Linux常用命令(3)

    文件处理命令         命令名称:touch 命令英文原意:touch 命令所在路径:/bin/touch 执行权限:所有用户 功能描述:创建空文件 语法:touch[文件名] 范例: $tou ...

  7. 用python写桌面天气预报,自己的学习曲线。

    自从接触python,就被他优雅而简洁的代码所吸引. 举个例子: arr , , , , , , , , , , , , , ] ] 如果用其他语言来写的吗,不会这么简洁,美观.   python还有 ...

  8. python中作用域

    Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的. 函数定义了本地作用域,而模块定义的是全局作用域.如果想要在函数内定义全局作用域,需要加上global修饰符. 变量名解析:LEG ...

  9. 洛谷P3120 [USACO15FEB]牛跳房子(动态开节点线段树)

    题意 题目链接 Sol \(f[i][j]\)表示前\(i\)行\(j\)列的贡献,转移的时候枚举从哪里转移而来,复杂度\(O(n^4)\) 然后考虑每一行的贡献,动态开节点线段树维护一下每种颜色的答 ...

  10. JavaScript 常见面试题

    此文内容多为 JavaScript 对数组理解及运用. 1.如何消除一个数组里面重复的元素? var arr = [1, 2, 3, 3, 4, 4, 5, 5, 6, 1]; var newArr ...