首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

POJ 2406 Power Strings - KMP 算法求字符串最大循環次數

     編輯:關於C++

問題描述

給定字符串 s,定義冪運算 a^n 為字符串 a 重複 n 次。求最大的 n,使得 s = a^n 對某個字符串 a 成立。字符串長度 ≤ 1,000,000。

範例:

輸入:  abcd      aaaa      ababab
輸出:  1         4         3

核心洞察:KMP Next 陣列

設字符串長度為 L,next[L] 為最長真前綴同時也是後綴的長度。若 L % (L - next[L]) == 0,則字符串由長度為 L - next[L] 的子串循環構成,答案為 L / (L - next[L]);否則答案為 1。

KMP Next 陣列構建

void getNext(const string& s, vector& next) {
    int n = s.length();
    next.resize(n + 1);
    next[0] = -1;
    int i = 0, j = -1;
    while (i < n) {
        if (j == -1 || s[i] == s[j]) {
            next[++i] = ++j;
        } else {
            j = next[j];
        }
    }
}

完整解題代碼

#include 
#include 
#include 
#include 
using namespace std;

const int MAXN = 1000010;
char s[MAXN];
int nxt[MAXN];

void getNext(int len) {
    int i = 0, j = -1;
    nxt[0] = -1;
    while (i < len) {
        if (j == -1 || s[i] == s[j]) nxt[++i] = ++j;
        else j = nxt[j];
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    while (scanf("%s", s) == 1) {
        if (s[0] == '.') break;
        int len = strlen(s);
        getNext(len);
        int period = len - nxt[len];
        if (len % period == 0) 
            printf("%d\n", len / period);
        else 
            printf("1\n");
    }
    return 0;
}

關鍵點說明

  • 輸入處理:題目有巨大輸入,必須用 scanf 而非 cin,否則 TLE
  • Next 陣列含義:next[i] 表示前 i 個字符的最長公共前後綴長度
  • 循環節判定:len - next[len] 為最小循環節長度

複雜度分析

  • 時間複雜度:O(n),KMP 構建 next 陣列為線性
  • 空間複雜度:O(n),需存儲 next 陣列
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved