1. 程式人生 > 其它 >web刷題總結(未完.......)

web刷題總結(未完.......)

Luogu P1944 最長括號匹配

Luogu P1944 最長括號匹配

顯然是一道 DP。

設 $f_i$ 為以第 $i$ 位結尾的最長括號匹配子串的長度。

則當 s[i-f[i-1]-1]s[i] 匹配時,$f_i=f_{i-1}+2+f_{i-f_{i-1}-2}$。$f_{i-f_{i-1}-2}$ 表示這個匹配之前可能存在的一個匹配的長度。

特別注意的是,不要在 for 迴圈裡寫 strlen(s),這樣每次迴圈的時候都要計算一次,會有三個點超時。

程式碼實現如下:

#include<bits/stdc++.h>
#define N 1000010

int ans,pos;
int f[N];
char s[N];

namespace WalkerV {
	void Read() {
		scanf("%s",s);
		return;
	}

	void Solve() {
		int len=strlen(s);
		for(int i=0;i<len;i++) {
			if(s[i]==')') {
				if(s[i-f[i-1]-1]=='(') {
					f[i]=f[i-1]+2+f[i-f[i-1]-2];
				}
			}
			if(s[i]==']') {
				if(s[i-f[i-1]-1]=='[') {
					f[i]=f[i-1]+2+f[i-f[i-1]-2];
				}
			}
			if(ans<f[i]) {
				ans=f[i];
				pos=i;
			}
			//printf("f[%d]:%d\n",i,f[i]);
		}
		return;
	}

	void Print() {
		//printf("%d %d\n",ans,pos);
		for(int i=pos-ans+1;i<=pos;i++) {
			printf("%c",s[i]);
		}
		printf("\n");
		return;
	}
}

int main()
{
	WalkerV::Read();
	WalkerV::Solve();
	WalkerV::Print();
	return 0;
}