1. 程式人生 > >字串中的最大值(KMP)

字串中的最大值(KMP)

【題目描述】 在這裡插入圖片描述

【思路】 假設現在有一個位置 pospos ,其字首已經出現一次即 [0,pos1][0,pos-1] 這個字首已經出現了一次,現在考慮一下 next[pos]next[pos] 的意義,其實就是包含在 [0,pos1][0,pos-1] 這個字首裡面的字首(字首針對整個字串而言,並非 [0,pos1][0,pos-1] 這個子串),也就是如果我們能夠知道一個前綴出現的次數,那麼包含在這個字首裡面的字首也應當又出現了一次,所以只要跑一遍 KMP 得到 nextnext 陣列,然後對每一個前綴出現的次數都疊加到其包含的字首當中去,即狀態轉移方程 d

p[next[i]]+=dp[i]dp[next[i]] += dp[i] ( d[i]d[i] 代表長度為 ii 的前綴出現的次數),整個過程應該是逆推的

#include<bits/stdc++.h>
using namespace std;

const int maxn=100005;

char p[maxn];
int nxt[maxn],lenp;
long long dp[maxn];

void getnext(){
	nxt[0]=-1;
	int j=0,k=-1;
	while(j<lenp){
		if(k==-1 || p[k]==p[j]){
			++j;
			++k;
			nxt[j]=k;
		}
		else k=nxt[k];
	}
}

int main(){
	scanf("%s",p);
	lenp=strlen(p);
	getnext();
	for(int i=1;i<=lenp;++i) dp[i]=1;
	for(int i=lenp;i>=1;--i) dp[nxt[i]]+=dp[i];
	long long ans=0;
	for(int i=1;i<=lenp;++i) ans=max(ans,(long long)i*dp[i]);
	printf("%lld\n",ans);
	return 0;
}