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

51Nod 1277 - 字串中的最大值(KMP)

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

【思路】
假設現在有一個位置 p o s pos ,其字首已經出現一次即 [ 0 ,

p o s 1 ] [0,pos-1] 這個字首已經出現了一次,現在考慮一下 n
e x t [ p o s ] next[pos]
的意義,其實就是包含在 [
0 , p o s 1 ] [0,pos-1]
這個字首裡面的字首(字首針對整個字串而言,並非 [ 0 , p o s 1 ] [0,pos-1] 這個子串),也就是如果我們能夠知道一個前綴出現的次數,那麼包含在這個字首裡面的字首也應當又出現了一次,所以只要跑一遍 KMP 得到 n e x t next 陣列,然後對每一個前綴出現的次數都疊加到其包含的字首當中去,即狀態轉移方程 d p [ n e x t [ i ] ] + = d p [ i ] dp[next[i]] += dp[i] ( d [ i ] d[i] 代表長度為 i i 的前綴出現的次數),整個過程應該是逆推的

#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;
}