如输入括号,求解总子串和最长长度为多少,并求解有最长括号几种
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

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