题目描述
小 L 现在在玩一个低配版本的消消乐,该版本的游戏是一维的,一次也只能消除两个相邻的元素。
现在,他有一个长度为 n 且仅由小写字母构成的字符串。我们称一个字符串是可消除的,当且仅当可以对这个字符串进行若干次操作,使之成为一个空字符串。
其中每次操作可以从字符串中删除两个相邻的相同字符,操作后剩余字符串会拼接在一起。
小 L 想知道,这个字符串的所有非空连续子串中,有多少个是可消除的。
输入格式
输入的第一行包含一个正整数 n,表示字符串的长度。
输入的第二行包含一个长度为 n 且仅由小写字母构成的的字符串,表示题目中询问的字符串。
输出格式
输出一行包含一个整数,表示题目询问的答案。
输入输出样例
输入 #1复制
8 accabccb输出 #1复制
5说明/提示
【样例 1 解释】
一共有 55 个可消除的连续子串,分别是
cc
、acca
、cc
、bccb
、accabccb
。【样例 2】
见选手目录下的
game/game2.in
与game/game2.ans
。【样例 3】
见选手目录下的
game/game3.in
与game/game3.ans
。【样例 4】
见选手目录下的
game/game4.in
与game/game4.ans
。【数据范围】
对于所有测试数据有:1≤n≤2×10^6,且询问的字符串仅由小写字母构成。
测试点 n≤ 特殊性质 1∼5 10 无 6∼7 800 无 8∼10 8000 无 11∼12 2×10^5 A 13∼14 2×10^5 B 15∼17 2×10^5 无 18∼20 2×10^6 无 特殊性质 A:字符串中的每个字符独立等概率地从字符集中选择。
特殊性质 B:字符串仅由
a
和b
构成。附件下载
game.zip153.28KB
代码:
1.暴力解
#include <bits/stdc++.h>
using namespace std;
int n;
string s;
bool solve(int l,int r){
stack<int> st;//用栈处理消除操作 后进先出
for(int i = l;i<=r;i++){
if(st.size()){
if(s[i]==st.top()) st.pop();
//如果当前字母和栈顶字母一样,说明相邻,可以消除
else st.push(s[i]);
//如果不一样放进栈里
}else st.push(s[i]);//如果栈是空的放进去
}
if(st.size()==0) return true;
//如果操作完之后栈里没有元素,说明可以消除完,合法
else return false;
//13,14行可以换为 return (st.size()==0);
}
int main(){
cin >> n >> s;
int sum=0;
for(int i = 0;i<s.size();i++){//枚举起点
for(int j = i;j<s.size();j++){//枚举终点
sum+=solve(i,j);//如果子串合法返回1否则返回零
}
}
cout << sum;
return 0;
}