1304 字符串的相似度 后缀数组

简介: 1304 字符串的相似度 后缀数组

我们定义2个字符串的相似度等于两个串的相同前缀的长度。例如 “abc” 同 “abd” 的相似度为2,“aaa” 同 “aaab” 的相似度为3。

给出一个字符串S,计算S同他所有后缀的相似度之和。例如:S = “ababaa”,所有后缀为:


ababaa 6

babaa 0

abaa 3

baa 0

aa 1

a 1


S同所有后缀的相似度的和 = 6 + 0 + 3 + 0 + 1 + 1 = 11


输入

输入一个字符串S(1 <= L <= 1000000),L为字符串S的长度,且S由a-z的小写字母组成。

输出

输出S同所有后缀的相似度的和。

输入样例

ababaa

输出样例

11


后缀数组模板题,倍增算法O(nlogn)复杂度的过不去,需要DC3算法O(n)复杂度才能卡过去(正解是exKMP算法)但是我不会


倍增算法

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
char s[maxn];
int height[maxn], sa[maxn], tx[maxn], rak[maxn];
struct node {
  int x, y, id;
}a[maxn], b[maxn];
int n, m, p;
void rsort() {
  for (int i = 1; i <= m; i++) {
    tx[i] = 0;
  }
  for (int i = 1; i <= n; i++) {
    tx[a[i].y]++;
  }
  for (int i = 1; i <= m; i++) {
    tx[i] += tx[i - 1];
  }
  for (int i = 1; i <= n; i++) {
    b[tx[a[i].y]--] = a[i];
  }
  for (int i = 1; i <= m; i++) {
    tx[i] = 0;
  }
  for (int i = 1; i <= n; i++) {
    tx[b[i].x]++;
  }
  for (int i = 1; i <= m; i++) {
    tx[i] += tx[i - 1];
  }
  for (int i = n; i >= 1; i--) {
    a[tx[b[i].x]--] = b[i];
  }
}
void ssort() {
  rsort();
  p = 0;
  for (int i = 1; i <= n; i++) {
    if (a[i].x != a[i - 1].x || a[i].y != a[i - 1].y) {
      ++p;
    }
    rak[a[i].id] = p;
  }
  for (int i = 1; i <= n; i++) {
    a[i].x = rak[i];
    a[i].id = sa[rak[i]] = i;
    a[i].y = 0;
  }
  m = p;
}
void solve() {
  m = 127;
  for (int i = 1; i <= n; i++) {
    a[i].x = a[i].y = s[i];
    a[i].id = i;
  }
  ssort();
  for (int j = 1; j <= n; j <<= 1) {
    for (int i = 1; i + j <= n; i++) {
      a[i].y = a[i + j].x;
    }
    ssort();
    if (p == n) {
      break;
    }
  }
}
void get_Height() {
  int k = 0;
  for (int i = 1; i <= n; i++) {
    if (k) {
      k--;
    }
    int j = sa[rak[i] - 1];
    while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) {
      k++;
    }
    height[rak[i]] = k;
  }
}
int main() {
  scanf("%s", s + 1);
  n = strlen(s + 1);
  solve(); get_Height();
  long long ans = 0;
  int mm = 1e9;
  for (int i = rak[1] + 1; i <= n; i++) {
    mm = min(mm, height[i]);
    ans += mm;
  }
  mm = 1e9;
  for (int i = rak[1]; i >= 1; i--) {
    mm = min(mm, height[i]);
    ans += mm;
  }
  cout << ans + n << endl;
  return 0;
}
相关文章
|
6月前
|
机器学习/深度学习 算法 JavaScript
【动态规划】【回文】【字符串】1278分割回文串 III
【动态规划】【回文】【字符串】1278分割回文串 III
|
6月前
|
机器学习/深度学习 算法 测试技术
【组合数学 容斥原理 逆向思考】2930. 重新排列后包含指定子字符串的字符串数目
【组合数学 容斥原理 逆向思考】2930. 重新排列后包含指定子字符串的字符串数目
|
11月前
|
算法 测试技术 C++
C++算法:分割回文串
C++算法:分割回文串
|
6月前
|
人工智能 算法 测试技术
【字符串】【C++算法】828.统计子串中的唯一字符
【字符串】【C++算法】828.统计子串中的唯一字符
|
6月前
|
存储 算法 程序员
【算法训练-字符串 一】【子串问题】最长无重复子串、最长回文子串、最长公共前缀
【算法训练-字符串 一】【子串问题】最长无重复子串、最长回文子串、最长公共前缀
67 0
【每日挠头算法题(8)】最后一个单词的长度|重新排列字符串
【每日挠头算法题(8)】最后一个单词的长度|重新排列字符串
|
存储
Leecoe 72. 编辑距离
Leecoe 72. 编辑距离
33 0
|
算法 Java 索引
【算法】给定一个字符串 s 和一些长度相同的单词 words,串联所有单词的子串。要不要来试一试?
给定一个字符串 s 和一些长度相同的单词 words串联所有单词的子串
146 0
【算法】给定一个字符串 s 和一些长度相同的单词 words,串联所有单词的子串。要不要来试一试?