解题思路

这是一个字符串前缀的最长重复词问题。需要找到每个前缀的最长重复词,并计算所有长度之和。

关键点:

  1. 重复词必须是真前缀
  2. 原串必须是重复词两次的前缀
  3. 使用动态规划记录每个位置的最长重复词长度
  4. 优化字符串匹配过程

算法步骤:

  1. 找到与首字符相同的所有位置
  2. 从后向前检查每个可能的重复词
  3. 验证重复词的有效性
  4. 累加所有前缀的最长重复词长度

代码

#include<bits/stdc++.h>
using namespace std;
class Periods {
public:
    long long getLongest(int n, string s) {
        vector<long long> ans(n, 0);
        char startChar = s[0];
        vector<int> startIndex;
        
        // 找到所有与首字符相同的位置
        for (int i = 1; i < n; i++) {
            if (s[i] == startChar) {
                startIndex.push_back(i);
            }
        }
        
        // 从后向前处理每个可能的起始位置
        for (int i = startIndex.size() - 1; i >= 0; i--) {
            int index = startIndex[i];
            ans[index] = index;
            long long ansTemp = index;
            int temp = 1;
            index++;
            
            while (index < n && (temp + 1) * 2 <= (index + 1) 
                   && s[index] == s[temp]) {
                ans[index] = max(ans[index], ansTemp);
                index++;
                temp++;
            }
        }
        
        // 计算总和
        return accumulate(ans.begin(), ans.end(), 0LL);
    }
};
import java.util.*;

public class Periods {
    public long getLongest(int n, String s) {
        // 初始化答案数组
        long[] ans = new long[n];
        char startChar = s.charAt(0);
        List<Integer> startIndex = new ArrayList<>();
        
        // 找到所有与首字符相同的位置
        for (int i = 1; i < n; i++) {
            if (s.charAt(i) == startChar) {
                startIndex.add(i);
            }
        }
        
        // 从后向前处理每个可能的起始位置
        for (int i = startIndex.size() - 1; i >= 0; i--) {
            int index = startIndex.get(i);
            ans[index] = index;
            long ansTemp = index;
            int temp = 1;
            index++;
            
            while (index < n && (temp + 1) * 2 <= (index + 1) 
                   && s.charAt(index) == s.charAt(temp)) {
                ans[index] = Math.max(ans[index], ansTemp);
                index++;
                temp++;
            }
        }
        
        // 计算总和
        long sum = 0;
        for (long val : ans) {
            sum += val;
        }
        return sum;
    }
}
# -*- coding:utf-8 -*-
class Periods:
    def getLongest(self, n, s):
        # 初始化答案数组,记录每个位置的最长重复词长度
        ans = [0 for i in range(n)]
        
        # 获取首字符
        start_c = s[0]
        start_index = []
        
        # 找到所有与首字符相同的位置
        for i in range(1, n):
            if s[i] == start_c:
                start_index.append(i)
        
        # 从后向前处理每个可能的起始位置
        for index in start_index[::-1]:
            ans[index] = index
            ans_temp = index
            temp = 1
            index += 1
            
            # 检查是否可以继续扩展重复词
            while index < n and (temp + 1) * 2 <= (index + 1) and s[index] == s[temp]:
                ans[index] = max(ans[index], ans_temp)
                index += 1
                temp += 1
        
        # 返回所有长度之和
        return sum(ans)

算法及复杂度

  • 算法:动态规划 + 字符串匹配
  • 时间复杂度:,其中 是字符串长度
  • 空间复杂度:,用于存储答案数组和起始位置数组