两道字符串水题 记录一下 zjut 1605 和 zjut 1703

Regular BracketsZJUT1605 题意是给一系列括号,只有[]和()是匹配的,还有[R],(R),[]R,()R,R[],R()这几种是匹配的。问最长的匹配的字串是什么。原题的数据量只有100,实际可以提高到100000,因为是O(N)的算法。大概是用栈保存那些未被匹配的字符和其位置,然后从栈顶到尾找到那些每两个相邻栈元素之间的距离最长的即可。注意的是要把首尾考虑进去。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<queue>
#include<stack>
using namespace std;

struct qiueji
{
	char c;
	int num;
};

int main()
{
	string s;
	while(cin>>s)
	{
		int i,j,max=0,jilu=0;
		vector<qiueji> v(s.length()+5);
		for(i=0;i<s.length();i++)
		{
			v[i].c=s[i];
			v[i].num=i;
		}
		stack<qiueji> st;
		for(i=0;i<s.length();i++)
		{
			if(st.empty()) st.push(v[i]);
			else if(st.top().c=='(' && v[i].c==')')
				st.pop();
			else if(st.top().c=='[' && v[i].c==']')
				st.pop();
			else st.push(v[i]);
		}
		if(!st.empty())
		{
			int tt=s.length()-1-st.top().num;
			if(tt>=max) {max=tt;jilu=st.top().num+1;}
		}
		else { max=s.length();jilu=0;}
		qiueji t;
		int judge=0;
		while(!st.empty())
		{
			t=st.top();
			judge=1;
			st.pop();
			if(!st.empty())
			{
				int tt=t.num-st.top().num-1;
				if(tt>=max) {max=tt;jilu=st.top().num+1;}
			}
		}
		if(judge && t.num>=max) {max=t.num;jilu=0;}
		st.push(v[s.length()]);
		for(i=jilu;i<jilu+max;i++)
			cout<<s[i];
		cout<<endl<<endl;
	}
}


Position Arrangement ZJUT1703 是给一个01字符串,每次只能进行一个交换相邻符号的操作,问最少经过几次操作可以将1全部移到一起。一开始的想法是把最左边的1和最右边的1中间所有的0都和两边1的位置比较一下然后取最小,然后处理两边1的位置即可。后来发现,这样做的话是不一定对的,后来请教csn大神,说是比较每个0两边1的个数就可以了,发现真有道理,因为0和0交换就浪费了。O(N)的复杂度。


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<queue>
#include<stack>
using namespace std;

int min(int a,int b)
{
	if(a<b) return a;
	return b;
}

int main()
{
	string s;
	int m=1,i,j,k;
	while(cin>>s)
	{
		int front=-1,back=-1;
		for(i=0;i<s.length();i++)
			if(s[i]=='1') {front=i;break;}
		for(i=s.length()-1;i>=0;i--)
			if(s[i]=='1') {back=i;break;}
		int zeros=0;
		if(front==back) { printf("Case #%d: %d\n",m++,0);continue;}
		int sum=0;
		for(i=front;i<=back;i++)
		{
			if(s[i]=='0') zeros++;
		}
		vector<int> lzero(zeros),rzero(zeros);
		for(i=front,j=0,k=0;i<=back;i++)
		{
			if(s[i]=='1') j++;
			else lzero[k++]=j;
		}
		for(i=back,j=0,k=zeros-1;i>=front;i--)
		{
			if(s[i]=='1') j++;
			else rzero[k--]=j;
		}
		for(i=0;i<zeros;i++)
			sum+=min(lzero[i],rzero[i]);
		printf("Case #%d: %d\n",m++,sum);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值