雕刻时光

just do it……nothing impossible
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

对括号匹配问题的在深入思考

Posted on 2012-01-12 20:44  huhuuu  阅读(426)  评论(0编辑  收藏  举报

如输入括号,求解总子串和最长长度为多少,并求解有最长括号几种

8
(())))))

(())最长为4,有C(6,2)=15种;(最后的‘)’,‘)’可以在后面6个里面选2个)

显然:

16
(())))))(())))))

输出:8 225

32
(())))))(())))))(())))))(())))))

输出:16 50625

14
()()()()()()()

输出:14 1

14
)()()()))((())

输出:10 9

4
)))(

输出:0 1

 

总子串和最长长度好算,如何求解它有几种呢

开个hash[]

如对于 (()))))),将可以匹配的'('写为1,‘)’写为2,不能匹配的写为0

11220000

220000为6个数,‘2’有2

则算组合数C(6,2)

(())))))(())))))

同理C(6,2)*C(6,2)

 

如果)()()()))((())

01212120011122

组合数算出来就只有3个,显然不对

解决办法,将括号序列镜像转置后

(()))((()()()(

11220111212121

就可以将另外的C(3,2)算出来,总的就是3*3=9

 

View Code
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

char a[1000009];

long long ahash[1000009];

long long min(long long a,long long b)
{
if(a>b)return b;
else return a;
}

long long cal(long long a,long long b)
{
a=min(a,b-a);
double up=a,down=b,all=1;

long long i;
for(i=0;i<up;i++)
{
all=all*(down-i)/(up-i);
}

return (int)all;
}

int main()
{
long long n;
while(scanf("%lld",&n)!=EOF)
{
long long i,j,add=0;

memset(ahash,0,sizeof(ahash));

scanf("%s",a);
long long ss=0;
long long all=1;

int ci=2;
while(ci--)
{
if(ci==0)
{
memset(ahash,0,sizeof(ahash));
for(i=0;i<n/2;i++)
{
char t;
t=a[i];
a[i]=a[n-1-i];
a[n-1-i]=t;

if(a[i]=='(')a[i]=')';
else a[i]='(';

if(a[n-1-i]==')')a[n-1-i]='(';
else a[n-1-i]=')';
}
}

ss=0;
add=0;
for(i=0;i<n;i++)
{
if(ss==0&&a[i]=='(')
{
ss++;
ahash[i]=1;
continue;
}

if(ss!=0)
{
if(a[i]==')')
{
add+=2;
ahash[i]=2;
ss--;
}
else
{
ahash[i]=1;
ss++;
}
}
}



for(i=0;i<n;i++)
{
if(a[i]=='(')
break;
}

for(i;i<n;i++)
{
if(ahash[i]!=0)continue;

long long oadd=1;
for(j=i+1;j<n;j++)
{
if(ahash[j]==0)
oadd++;
else
break;
}

long long r=j-1;

long long sadd=1;
for(j=i-2;j>=0;j--)
{
if(ahash[i-1]==ahash[j])
sadd++;
else
break;
}

all=all*cal(sadd,sadd+oadd);

i=r;
}
}

if(add==0)
printf("0 1\n");
else
printf("%lld %lld\n",add,all);
}
}