HihoCoder - 1110 Regular Expression区间dp

描述
给定一个字符串,判断其是否为合法的正则表达式。

 一个正则表达式定义为:

 1:0是正则表达式,1也是正则表达式。

 2:P和Q都是正则表达式,则PQ是正则表达式。

 3:P是正则表达式,则(P)是正则表达式

 4:P是正则表达式,则P*也是正则表达式

 5:P和Q都是正则表达式,则P|Q是正则表达式。

输入
输入包含多组数据。

每组数据为一行一个字符串,长度不超过100。

输出
对于每组数据,如果输入是合法的正则表达式,输出yes,否则输出no。

样例输入
010101101*
(11|0*)*
)*111
样例输出
yes
yes
no
 

思路:dp接触的较少,所以没有一眼看出是用dp,还以为是用栈呢(ˉ▽ˉ;)...

这题很简单的区间dp

dp[i][j] 表示字符s[i]到s[j]是否是正则表达式,若是置1,否置0,当然,最开始全部置0;

先遍历一遍,把单个字符为0,1的情况解决掉,然后进行区间的更新

更新的原则是按照区间的大小,比如说先是更新区间长度为1的,从头到尾把所有区间长度为1的都判断完,再进行长度为2的......

注意:判断的时候,()和*可以直接根据区间的左右端点来判断,而 | 和PQ则是要取一个中间值,只要设置一个变量k遍历i到j即可

看代码把

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	std::ios::sync_with_stdio(false);
	int dp[105][105];
	char s[105];
	while(~scanf("%s",s))
	{
		memset(dp,0,sizeof(dp));
		int i,j,k;
		int len=strlen(s);
		for(i=0;i<len;i++)
			if(s[i]=='0'||s[i]=='1') dp[i][i]=1;
			
		for(int l=1;l<len;l++) //循环判断区间的长度 
		{
			for(i=0;i<len;i++)
			{
				int j=i+l;
				if(s[i]=='('&&s[j]==')'&&dp[i+1][j-1]) dp[i][j]=1;
				if(s[j]=='*'&&dp[i][j-1]) dp[i][j]=1;
				for(k=i;k<=j;k++)
				{
					if(dp[i][k]&&dp[k+1][j]) dp[i][j]=1;
					if(s[k]=='|'&&dp[i][k-1]&&dp[k+1][j]) dp[i][j]=1;
				}
			}
		}
		cout<<(dp[0][len-1]?"yes":"no")<<endl;
	}
	return 0;

猜你喜欢

转载自blog.csdn.net/zvenWang/article/details/84780811
今日推荐