描述
给定一个字符串,判断其是否为合法的正则表达式。
一个正则表达式定义为:
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;