HDU problem 5635 LCP Array【思维】

谁借莪1个温暖的怀抱¢ 2022-01-10 04:37 257阅读 0赞

LCP Array

Accepts: 131

Submissions: 1352

Time Limit: 4000/2000 MS (Java/Others)

Memory Limit: 131072/131072 K (Java/Others)

问题描述

  1. s=s_{1}s_{2}...s_{n}s=s1s2...sn, \text{suff}_i =s_{i}s_{i+1}...s_{n}suffi=sisi+1...snssii字符开头的后缀. Peter知道任意两个相邻的后缀的最长公共前缀a_i = \text{lcp}(\text{suff}_i, \text{suff}_{i+1}) \quad (1 \le i < nai=lcp(suffi,suffi+1)(1i<n). 现在给你数组aa, Peter有多少个仅包含小写字母的字符串满足这个数组. 答案也许会很大, 你只要输出对10^9 + 7109+7取模的结果即可.

输入描述

  1. TT, 表示测试数据的组数. 对于每组数据: 第一行包含一个整数nn (2 \le n \le 10^5)2n105)表示字符串的长度. 第二行包含n - 1n1个整数: a_1,a_2,...,a_{n-1}a1,a2,...,an1 (0 \le a_i \le n)(0ain). 所有数据中nn的和不超过10^6106.

输出描述

  1. 10^9+7109+7取模的结果.

输入样例

  1. 16250
  2. 26
  3. 0

题意: 给你一个含有N-1个元素的数组,数组对应一个长度为N的字符串,数组中的第i个数的含义为字符串中第i个开头的和第i+1个开头的字符串的子串的最大    公共前缀的长度,现在让你推算数这个字符串有多少种情况。

先把数组处理下,对于i个长度为0的子串,它的颜色和他的后面的元素的字母不相同,标记下。如果长度不为0,它的首字母必定和下个字母相同,然后利用最大长度检查剩下的是否也相同,要是不相同,则这组数据出错了。

利用记录的字符串的信息扫一下,如果某个位置的字符和它的后面的相同,则他的情况和后面支付的一样,否则它有25种可能性。

  1. #include <map>
  2. #include <set>
  3. #include <cstdio>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <queue>
  7. #include <iostream>
  8. #include <stack>
  9. #include <cmath>
  10. #include <string>
  11. #include <vector>
  12. #include <cstdlib>
  13. //#include <bits/stdc++.h>
  14. //#define LOACL
  15. #define space " "
  16. using namespace std;
  17. typedef long long LL;
  18. typedef __int64 Int;
  19. typedef pair<int, int> PAI;
  20. const int INF = 0x3f3f3f3f;
  21. const double ESP = 1e-5;
  22. const double PI = acos(-1.0);
  23. const int MOD = 1e9 + 7;
  24. const int MAXN = 1e5 + 10;
  25. int ar[MAXN], clor[MAXN];
  26. int main() {
  27. int T, N;
  28. scanf("%d", &T);
  29. while (T--) {
  30. memset(clor, 0, sizeof(clor));
  31. scanf("%d", &N);
  32. for (int i = 0; i < N - 1; i++) scanf("%d", &ar[i]);
  33. clor[N - 1] = 1;
  34. int cnt = 2;
  35. bool flag = false;
  36. for (int i = N - 2; i >= 0; i--) {
  37. if (ar[i] != 0) {
  38. clor[i] = clor[i + 1];
  39. for (int j = 1; j <= ar[i]; j++) {
  40. if (clor[i] != clor[i + j]) {flag = true; break;}
  41. }
  42. if (clor[i + ar[i] + 1] == clor[i]) {flag = true; break;}
  43. }
  44. else clor[i] = cnt++;
  45. if (flag) break;
  46. }
  47. Int ans = 26;
  48. // cout << "数据发生错误: " << flag <<endl;
  49. bool change = false;
  50. int temp = clor[N - 1];
  51. //for (int i = 0; i < N; i++) printf("第i个字母应该是%d\n", clor[i]);
  52. for (int i = N - 2; i >= 0; i--) {
  53. if (clor[i] != temp) {
  54. ans *= 25; temp = clor[i];
  55. ans %= MOD;
  56. }
  57. }
  58. if (flag) printf("%d\n", 0);
  59. else printf("%I64d\n", ans);
  60. }
  61. return 0;
  62. }

转载于:https://www.cnblogs.com/cniwoq/p/6770743.html

发表评论

表情:
评论列表 (有 0 条评论,257人围观)

还没有评论,来说两句吧...

相关阅读

    相关 HDU 6370(思维)

    [传送门][Link 1] 思路:因为狼说什么都是可以的,所以全是狼是可以,村民为0。 那问题就是转化成求铁狼的数量。我们对村民边建图,我们发现,一个连通分量要么是个基环树